perm filename PCPS04.PAS[S1,ALS]1 blob
sn#408338 filedate 1979-01-10 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00045 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00006 00002 (* *** V E R S I O N I N F O R M A T I O N P A G E *** *)
C00007 00003 (*PROGRAM HEADER PAGE*)
C00011 00004 (*********************************************************
C00026 00005 CONST DISPLIMIT = 20 MAXLEVEL = 10" MAXADDR = 16777215"(*XSL10*)
C00030 00006 TYPE (*DESCRIBING:*)
C00038 00007 VAR
C00044 00008 (*EXPRESSION COMPILATION:*)
C00047 00009 (** ERREXIT PRINTERROR FILL_BUFFER LISTLINE SKIP_E_DIRECTORY ENDOFLINE ERROR **)
C00053 00010 (** INSYMBOL SKIPBLNK NEXTCH OPTIONS **)
C00078 00011 (** ENTERID SEARCHSECTION SEARCHID GETBOUNDS **)
C00084 00012 (** PRINTTABLES MARKER MARKCTP MARKSTP MARKCTP FOLLOWCTP FOLLOWSTP **)
C00090 00013 (** FOLLOWCTP GENLABEL PRNTSYMBL PRNTVAR PRNTTYPE PRNTVAR **)
C00100 00014 (** SET_IN BUILD_SET **)
C00102 00015 (** BLOCK SKIP ALIGN CONSTANT **)
C00108 00016 (** COMPTYPES STRING **)
C00113 00017 (** TYP SIMPLETYPE **)
C00120 00018 (** FIELDLIST **)
C00128 00019 BEGIN (*TYP*)
C00137 00020 (** LABELDECLARATION CONSTDECLARATION TYPEDECLARATION **)
C00143 00021 (** VARDECLARATION **)
C00147 00022 (** PROCDECLARATION PARAMETERLIST **)
C00158 00023 BEGIN (*PROCDECLARATION*)
C00167 00024 (** PROCTYPE BODY PUTIC FLDW GETTYPE **)
C00172 00025 (** GEN0 GEN1 GEN2 PRINT_SET_OPND **)
C00179 00026 (** GEN3 LOAD STORE **)
C00183 00027 (** LOADADDRESS GENFJP GENUJPFJP GENCUPENT MKNAME GENDEF CHKBNDS PUTLABEL CTRGEN CTREMIT **)
C00192 00028 (** STATEMENT EXPRESSION SELECTOR **)
C00201 00029 (** CALL VARIABLE RWSETUP GETPUTRESETREWRITE READ1 **)
C00207 00030 (** WRITE1 PACK1 UNPACK1 **)
C00214 00031 (** NEW1 MARK1 RELEASE1 TRAPEXIT **)
C00219 00032 (** ABS1 SQR1 TRUNC1 ODD1 ORD1 CHR1 PREDSUCCTIM EOFEOLN MATH **)
C00230 00033 (** CALLNONSTANDARD **)
C00242 00034 (** EXPRESSION SIMPLEEXPRESSION TERM FACTOR **)
C00253 00035 BEGIN (*SIMPLEEXPRESSION*)
C00260 00036 (** ASSIGNMENT **)
C00268 00037 (** GOTOSTATEMENT COMPOUNDSTATEMENT IFSTATEMENT **)
C00274 00038 (** CASESTATEMENT REPEATSTATEMENT WHILESTATEMENT **)
C00284 00039 (** FORSTATEMENT WITHSTATEMENT **)
C00294 00040 BEGIN (*BODY*)
C00301 00041 (** MKNAME PROGRAMME STDNAMES ENTERSTDTYPES **)
C00315 00042 (** ENTSTDNAMES ENTERUNDECL **)
C00323 00043 (** INITSCALARS INITSETS INITTABLES RESWORDS SYMBOLS RATORS PROCMNEMONICS **)
C00334 00044 (** INSTRMNEMONICS **)
C00337 00045 BEGIN (*PASCALCOMPILER*)
C00340 ENDMK
C⊗;
(* *** V E R S I O N I N F O R M A T I O N P A G E *** *)
(* This version modified from copy of PCPE02.PAS[S1,EJG] made 11/11/78 14:08 *)
(* This version modified from copy of PCPG02.PAS[1,PEG] made 11/11/78 11:35 *)
(* The full directory information for that version is:
PCPG02 PAS 1PEG 41.8 06-Nov-78 0947 205 1PEG E 11-Nov-78 09-Nov-78 T33
An unmodified copy of that version is kept in PCPG02.PAS[S1,EJG] *)
(*PROGRAM HEADER PAGE*)
(*PAS10 OPTIONS*) (*$D+,R32,X6,F1*) (*X10S1*)
(* DEFAULT
L+ OBJECT LISTING -
T+ RUNTIME CHECK +
D+ DEBUG AND POSTMORTEM DUMP -
E+ EXTERNAL CALLS TO LEVEL 1 PROCEDURES ALLOWED -
U+ 72 COLUMN FORMAT -
Sn MAX INSTRUCTIONS PER STATEMENT 1000
Rn SIZE OF LOW-SEGMENT (SEE PAS10 MANUAL)
I+ FORTRAN I/O IN EXTERNAL FORTRAN SUBROUTINES -
Xn HIGHEST REGISTER FOR PARAMETERS 6
Fn FILE OPTION 1
*)
(*SLAC PCPASC OPTIONS*) (* D+,M-,B+*)
(* DEFAULT
L+ LIST SOURCE PROGRAM +
T+ PRINT SYMBOL TABLES (FOR POST-PROCESSOR) -
D+ RUNTIME CHECKING OF POINTER, INDEX, SUBRANGE VALUES -
E+ FILE IS IN EBCDIC CHARACTER SET -
U+ GET STATISTICS?? 2ND PARAMETER TO PCODE BGN INSTR. -
S+ SAVE GPR'S ON PROCEDURE/FUNCTION ENTRY +
X+ USE ACTUAL PROCEDURE NAMES FOR EXTERNAL REFERENCES -
X- GENERATE UNIQUE 8-CHAR NAMES FOR EXTERNAL REFERENCES
F+ SAVE FPR'S ON PROCEDURE/FUNCTION ENTRY +
C+ EMIT PCODE +
M+ 72 COLUMN FORMAT +
A+ GENERATE 370 OBJECT MODULE -
A- GENERATE 370 ASSEMBLY MODULE
B+ BOUNDS CHECKING, BUT ALLOW 'BIG' CHARACTERS -
K+ ENABLE STATEMENT EXECUTION COUNTING -
V+ ?? 3RD PCODE BGN INSTRUCTION PARAMETER -
P+ DOUBLE-WORD BOUNDARY ALIGNMENT -
*)
(*S1 PCPASC OPTION DIFFERENCES*) (* A+,B+,M120*) (*X10S1*)
(* DEFAULT
A+ GENERATE S1 ASSEMBLY MODULE -
A- GENERATE S1 OBJECT MODULE
Mn MARGIN LENGTH 80
N+ LAST 8 COLS. (MARGIN - 8 TO MARGIN) -
INTERPRETED AS SEQUENCE NUMBERS
*)
(*XSL10 MARKS CHANGES FOR TRANSPORTING FROM SLAC TO PDP10*)
(*TRANSLATE "@" TO "↑" XSL10*)
(*SETCH MARKS CHANGES MADE TO ENLARGE SET SIZE*)
(*X10S1 MARKS CHANGES FOR TRANSPORTING FROM PDP10 TO S-1*)
PROGRAM PCPASC(INPUT*,OUTPUT,PRR); (*XSL10-- '*' AFTER INPUT FILES*) (*X10S1*)
(*PROGRAM PCPASC(INPUT,OUTPUT,PRR);*) (*X10S1*)
(*********************************************************
* *
* *
* STEP-WISE DEVELOPMENT OF A PASCAL COMPILER *
* ****************************************** *
* *
* *
* STEP 5: SYNTAX ANALYSIS INCLUDING ERROR *
* HANDLING; CHECKS BASED ON DECLARA- *
* 10/7/73 TIONS; ADDRESS AND CODE GENERATION *
* FOR A HYPOTHETICAL STACK COMPUTER *
* *
* *
* AUTHOR: URS AMMANN *
* FACHGRUPPE COMPUTERWISSENSCHAFTEN *
* EIDG. TECHNISCHE HOCHSCHULE *
* CH-8006 ZUERICH *
* *
* *
* *
* MODIFICATION OF STEP 5 OF PASCAL COMPILER *
* ***************************************** *
* *
* THE COMPILER IS NOW WRITTEN IN A SUBSET OF *
* STANDARD PASCAL - AS DEFINED IN THE NEW *
* MANUAL BY K. JENSEN AND N. WIRTH - AND IT *
* PROCESSES EXACTLY THIS SUBSET. *
* *
* AUTHOR OF CHANGES: KESAV NORI *
* COMPUTER GROUP *
* T.I.F.R. *
* HOMI BHABHA ROAD *
* BOMBAY - 400005 *
* INDIA *
* *
* THESE CHANGES WERE COMPLETED AT ETH, ZURICH *
* ON 20/5/74. *
* *
* *
* *
* +++++++++++++++++++++++++++++++++++++++++++ *
* *
* *
* *
* THE COMPILER IS NOW CHANGED TO: *
* ******************************* *
* *
* *
* -PRODUCE THE INTERMEDIATE CODE IN AN *
* ASSEMBLER READABLE FORM (NAMELY THE *
* 370, ASSEMBLER_H), 15-NOV-75. *
* *
* -PRESERVE PROCEDURE NAMES AND THEIR *
* STATIC LEVELS AT THE OBJECT LEVEL, THUS *
* ALLOWING A SET OF 'DISPLAY' REGISTERS TO *
* BE USED IN ACCESSING NON_LOCAL, NON_GLOBAL *
* VARIABLES (INSTEAD OF GOING THROUGH A *
* CHAIN OF POINTERS), 10-DEC-75. *
* *
* -INCLUDE THE TYPE OF THE OPERANDS IN THE *
* P_INSTRUCTIONS AS FOLLOWS: *
* *
* A : ADDRESS (POINTER) OPERAND *
* B : BOOLEAN " *
* C : CHARACTER " *
* I : INTEGER " *
* R : REAL " *
* S : SET " *
* *
* THE P_INSTRUCTION NOW LOOKS LIKE: *
* (LAB) OPCODE (TYPE),(OPERANDS) *
* A NEW PROCEDURE 'EXIT(RC: INTEGER)' IS *
* ADDED TO THE SET OF STANDARD PROCEDURES *
* TO FACILITATE TERMINATING A PROGRAM AT *
* ANY POINT AND RETURNING A 'RETURN CODE' *
* TO THE OPERATING SYSTEM, 26-JAN-76. *
* *
* -TREAT THE INPUT AS A TEXT FILE WITH *
* LINES (RECORDS) OF 80 CHARACTER EACH, *
* THIS ALLOWS A MORE EFFICIENT STRING *
* ORIENTED INPUT, 20-MAR-76. *
* *
* -ALLOCATE AND PROPERLY ALIGN VARIABLES ON *
* THE BASIS OF THEIR TYPES, I.E. *
* *
* TYPE SIZE ALIGNED ON *
* *
* B,C 1-BYTE 1-BYTE *
* A,I 4-BYTES 4-BYTE *
* S 8-BYTES 4-BYTE *
* R 8-BYTES 8-BYTE *
* *
* DYNAMIC STORAGE HOWEVER IS ALWAYS ALLOC- *
* CATED ON 8-BYTE BOUNDARIES TO AVOID RUN- *
* TIME CHECKING OVERHEAD, 25-APR-76. *
* *
* -'READ' OF 'STRING' VARIABLES (I.E. ARRAY *
* OF CHAR) IS NOW IMPLEMENTED AND IT IS TO *
* COMPLEMENT THE SIMILAR 'WRITE' FUNCTION. *
* ALSO THE STANDARD PROCEDURE: *
* TRAP(I: INTEGER; VAR V: [ANY TYPE] ); *
* IS ADDED TO THE SET OF STANDARD PROCEDURES *
* TO FACILITATE COMMUNICATION WITH THE OUT- *
* SIDE WORLD, 10-SEP-76. *
* *
* -RELEVENT INFORMATION ON/ABOUT PROCEDURES *
* ARE NOW SENT TO 'QRR' FILE. THIS INCLUDES *
* SUCH INFORMATION AS THE SIZE OF THE PROCE- *
* DURE AS WELL AS ITS DATA AREA, LIST OF THE *
* PROCEDURES CALLED AND THE # OF CALLS, THE *
* LEVEL OF THE HIGHEST_LEVEL PROCEDURE CALLED *
* ETC. THIS INFORMATION IS MAINLY INTENDED *
* FOR INTER_PROCEDURAL ANALYSIS, BUT IT IS *
* ALSO USEFUL FOR MORE EFFICIENT PROCEDURE *
* ENTRY/EXIT CODE, 22-MAR-77. *
* *
* -TYPES "TEXT" (FILE OF CHAR) AND "ALFA" *
* (PACKED ARRAY [1..10] OF CHAR) ARE NOW *
* ADDED TO THE SET OF PREDEFINED TYPES, *
* 20-MAY-78. *
* *
* -I/O RELATED STANDARD PROCEDURES ARE NOW *
* MODIFIED TO CONFORM TO THE PASCAL 6000 *
* ABBREVIATIONS. EXPRESSIONS SUCH AS *
* "EOF(INPUT)" "EOF()" AND "EOF" ARE NOW *
* EQUIVALENT, 20-MAY-78. *
* *
* -REAL VALUES MAY BE PRINTED IN *
* SCIENTIFIC NOTATION OR THE SO CALLED *
* F_FORMAT DEPENDING ON THE FIELD *
* SPECIFICATION IN THE 'WRITE' / 'WRITELN' *
* STATEMENT. A SIMPLE FIELD SPECIFIER OF *
* THE FORM "R : FLDW" RESULTS IN E_FORMAT *
* WHILE "R : FLDW:DFLD" GENERATES AN *
* F_FORMAT OUTPUT, 20-MAY-78. *
* *
* -'EXTERNAL' AND 'FORTRAN' PROCEDURES / *
* FUNCTIONS ARE NOW SUPPORTED. IN ORDER *
* TO MAKE THE EXTERNAL (CSECT) AND *
* INTERNAL NAMES IDENTICAL, THE NEW 'X' *
* OPTION SWITCH IS INTRODUCED. IF *
* PROCEDURE / FUNCTION NAMES IN A PROGRAM *
* ARE NOT DISTINCT WITHIN THE FIRST 8 *
* CHARACTERS, (A PROBLEM WHICH WILL *
* CONFUSE THE "LOADER") THE 'X-' OPTION *
* WILL GENERATE UNIQUE EXTERNAL NAMES FOR *
* ALL PROCEDURES IN THE PROGRAM, AND THESE *
* NAMES SHOULD BE USED FOR THE *
* CORRESPONDING EXTERNAL/FORTRAN ROUTINES, *
* OTHERWISE ONE SHOULD USE THE 'X+' OPTION *
* TO BE ABLE TO USE THE EXTERNAL NAMES WITH NO *
* CHANGE, 2-JUNE-78. *
* *
* *
* THE ABOVE CHANGES (INCLUDING ADDITIONS AND/OR *
* DELETIONS) HAVE BEEN TAGGED BY A '#' TAG AT *
* THE BEGINNING OR THE END OF AFFECTED LINES. *
* *
* *
* *
* S. HAZEGHI *
* *
* COMPUTATION RESEARCH GROUP *
* S.L.A.C. *
* *
* *
* *
*********************************************************)
CONST DISPLIMIT = 20; MAXLEVEL = 10;" MAXADDR = 16777215;"(*XSL10*)
MAXADDR = 1073741823; (*XSL10*)
INTSIZE = 4; "REALSIZE = 8;" REALSIZE = 4; (*XSL10*)
CHARDIF = 40B; (*CHARDIF*) (*X10S1*)
(*CHARDIF = 0; *) (*CHARDIF*) (*X10S1*)
" CHARSIZE = 1; BOOLSIZE = 1; SETSIZE = 16 ; PTRSIZE = 4; (*SET_CH*)"
"EJG" CHARSIZE = 1; BOOLSIZE = 1; SETSIZE = 8 ; PTRSIZE = 4; (*SET_CH*)
"S0" " LCAFTMST = 80; FPSAVEAREA = 32 ; RUNCHKAREA = 96 ; "
"S0" " DSPLYAREA = 72 ; FNCRSLT = 72 ; "
"S0" " (* SAVE AREAS, FUNCTION RETURN VALUE SPACE, DISPLAY AREA, ETC. *) "
"S0" " FIRSTFILBUF = 248 ; (* = LCAFTMST+RUNCHKAREA+DSPLYAREA *) "
"S0" " LASTFILBUF = 280 ; (* LAST FILE BUFFER / FIRST PROG. VARIABLE *) "
"S1" (* 'S1' CONSTANT DEFINITION *)
"S1" REGPRMAREA = 40 ; (* SHOULD BE A MULTIPLE OF '4' BYTES *)
"S1" LCAFTMST = 8 ; FPSAVEAREA = 0 ; RUNCHKAREA = 0 ; DSPLYAREA = 0 ;
"S1" FNCRSLT = 0 ; FIRSTFILBUF = 12 ; LASTFILBUF = 44 ;
### REALLNGTH = 20 ; DIGMAX = 19 (* REALLNGHT-1*) ; IDLNGTH = 12 ;
# STRGLNGTH = 64;" MAXINT = 2147483647;" (*XSL10*)
MAXINT = 34359738367; (*XSL10*)
(*SETCH...*)
"EJG Temporarily patch these values for old-fashioned, short sets 11/11/78
MAXSETEL = 143; (*MAX LEGAL (ORDINAL) VALUE OF A SET MEMBER*)
HOST_SET_SIZE = 64; (*NUMBER OF SET ELEMENTS IN THE HOST COMPILER*)
HOST_SET_MAX = 63; (*MAX LEGAL VALUE FOR A HOST SET ELEMENT*)
SETREP_MAX = 2; (*NUMBER OF HOST SETS USED TO REP SETS - 1*)
NUMOFSETOPND = 9; (*NUMBER OF OPERANDS OUTPUT FOR PCODE *)
EJG"
MAXSETEL = 63; (*MAX LEGAL (ORDINAL) VALUE OF A SET MEMBER*)
HOST_SET_SIZE = 64; (*NUMBER OF SET ELEMENTS IN THE HOST COMPILER*)
HOST_SET_MAX = 63; (*MAX LEGAL VALUE FOR A HOST SET ELEMENT*)
(*The following "1" should be "0", but triggers PCPASC 0..0 bug*)
SETREP_MAX = 1; (*NUMBER OF HOST SETS USED TO REP SETS - 1*)
NUMOFSETOPND = 4; (*NUMBER OF OPERANDS OUTPUT FOR PCODE *)
(*...SETCH*) (* LDC S,(---) INSTRUCTION*)
# OPMAX = 64 ; (* OPCODE RANGE *)
# BLANK12 = ' ' ;
# NRSW = 37 ;
NRSW_P1 = 38 ; (*NRSW + 1*) (*PEG*)
# NSPROC = 32 ;
"CTR" MAXCTR = 16384 ;
STD_CHCNTMAX = 301 ; (*MAX NUMBER OF CH IN ONE LINE + 1*)(*PEG*)
DEF_CHCNTMAX = 81 ; (*DEFAULT VALUE FOR CHCNTMAX*) (*PEG*)
TYPE (*DESCRIBING:*)
(*************)
(*BASIC SYMBOLS*)
(***************)
SYMBOL = (IDENT,INTCONST,REALCONST,STRINGCONST,NOTSY,MULOP,ADDOP,RELOP,
LPARENT,RPARENT,LBRACK,RBRACK,COMMA,SEMICOLON,PERIOD,ARROW,
COLON,DOTDOT,BECOMES,LABELSY,CONSTSY,TYPESY,VARSY,FUNCSY,PROGSY,
PROCSY,SETSY,PACKEDSY,ARRAYSY,RECORDSY,FILESY,FORWARDSY,
BEGINSY,IFSY,CASESY,REPEATSY,WHILESY,FORSY,WITHSY,
GOTOSY,ENDSY,ELSESY,UNTILSY,OFSY,DOSY,TOSY,DOWNTOSY,
# # THENSY,FRTRNSY,EXTRNSY,OTHERSY);
OPERATOR = (MUL,RDIV,ANDOP,IDIV,IMOD,PLUS,MINUS,OROP,LTOP,LEOP,GEOP,GTOP,
NEOP,EQOP,INOP,NOOP);
SETOFSYS = SET OF SYMBOL;
(*SETCH...*)
SETREP_INDEX = 0..SETREP_MAX;
SET_EL_TYP = 0..MAXSETEL;
SETREP = ARRAY[SETREP_INDEX] OF SET OF 0..HOST_SET_MAX;
(*...SETCH*)
(*CONSTANTS*)
(***********)
CSTCLASS = (REEL,PSET,STRG);
CSP = ↑ CONSTANT;
CONSTANT = RECORD CASE "CCLASS:" CSTCLASS OF
REEL: (RVAL: PACKED ARRAY [1..REALLNGTH] OF CHAR);
PSET: (PVAL: SETREP); (*SETCH*)
"(PVAL: SET OF 0..MAXSETEL);" (*SETCH*)
STRG: (SLNGTH: 0..STRGLNGTH;
SVAL: PACKED ARRAY [1..STRGLNGTH] OF CHAR)
END;
VALU = RECORD CASE "INTVAL:" BOOLEAN OF (*INTVAL NEVER SET NORE TESTED*)
TRUE: (IVAL: INTEGER);
FALSE: (VALP: CSP)
END;
(*DATA STRUCTURES*)
(*****************)
LEVRANGE = 0..MAXLEVEL; ADDRRANGE = 0..MAXADDR;
ALNRNG = 1..8 ; LABELRNG = 0..1000 ;
STRUCTFORM = (SCALAR,SUBRANGE,POINTER,POWER,ARRAYS,RECORDS,FILES,
TAGFLD,VARIANT);
DECLKIND = (STANDARD,DECLARED);
STP = ↑ STRUCTURE; CTP = ↑ IDENTIFIER;
STRUCTURE = PACKED RECORD
(* MARKED: BOOLEAN; TO BE USED WITH 'T+', FOR TEST PHASE ONLY*)
ALN : ALNRNG ; (*REQUIRED ALIGNMENT *)
SIZE: ADDRRANGE;
CASE FORM: STRUCTFORM OF
SCALAR: (CASE SCALKIND: DECLKIND OF
DECLARED: (FCONST: CTP));
SUBRANGE: (RANGETYPE: STP; MIN,MAX: VALU);
POINTER: (ELTYPE: STP);
POWER: (ELSET: STP);
ARRAYS: (AELTYPE,INXTYPE: STP);
RECORDS: (FSTFLD: CTP; RECVAR: STP);
FILES: (FILTYPE: STP);
TAGFLD: (TAGFIELDP: CTP; FSTVAR: STP);
VARIANT: (NXTVAR,SUBVAR: STP; VARVAL: VALU)
END;
(*NAMES*)
(*******)
IDCLASS = (TYPES,KONST,VARS,FIELD,PROC,FUNC);
SETOFIDS = SET OF IDCLASS;
IDKIND = (ACTUAL,FORMAL);
ALPHA = PACKED ARRAY [1..IDLNGTH] OF CHAR;
IDENTIFIER = PACKED RECORD
NAME: ALPHA; LLINK, RLINK: CTP;
IDTYPE: STP; NEXT: CTP;
CASE KLASS: IDCLASS OF
KONST: (VALUES: VALU);
# VARS: (VKIND: IDKIND; EBCD: BOOLEAN ;
VLEV: LEVRANGE; VADDR: ADDRRANGE);
FIELD: (FLDADDR: ADDRRANGE);
PROC,
FUNC: (CASE PFDECKIND: DECLKIND OF
STANDARD: (KEY: 1..NSPROC);
DECLARED: (PFLEV: LEVRANGE; PFNAME: LABELRNG;
"S1" FPRMSZE,RPRMSZE,SPRMSZE: ADDRRANGE;
CASE PFKIND: IDKIND OF
ACTUAL: (FWDECL, EXTRN,FRTRN,SAVEFP:
BOOLEAN)))
END;
DISPRANGE = 0..DISPLIMIT;
WHERE = (BLCK,CREC,VREC,REC);
(*EXPRESSIONS*)
(*************)
ATTRKIND = (CST,VARBL,EXPR);
VACCESS = (DRCT,INDRCT,INXD);
# ATTR = RECORD TYPTR, BTYPE: STP;
CASE KIND: ATTRKIND OF
CST: (CVAL: VALU);
VARBL: (CASE ACCESS: VACCESS OF
DRCT: (VLEVEL: LEVRANGE; DPLMT: ADDRRANGE);
INDRCT: (IDPLMT: ADDRRANGE))
END;
TESTP = ↑ TESTPOINTER;
TESTPOINTER = PACKED RECORD
ELT1,ELT2 : STP;
LASTTESTP : TESTP
END;
(*LABELS*)
(********)
LBP = ↑ LABL;
LABL = RECORD NEXTLAB: LBP; DEFINED: BOOLEAN;
LABVAL, LABNAME: INTEGER
END;
EXTFILEP = ↑FILEREC;
FILEREC = RECORD FILENAME:ALPHA; NEXTFILE:EXTFILEP; GEBCDFIL: BOOLEAN END;
"CTR" CTRRANGE = 0..MAXCTR;
"CTR" CTRTYPE = (CTRPROC, CTRLBL, CTRGOTO, CTRIF, CTRWHILE, CTRREPEAT,
"CTR" CTRFOR, CTRCASE);
(*-------------------------------------------------------------------------*)
VAR
PRD,PRR,QRR,QRD: TEXT; (*FILES MUST BE PRE-DECLARED*) (*XSL10*) (*X10S1*)
"E" SYMTBL:TEXT;
# ERRORCOUNT, CTIME: INTEGER; (*TOTAL ERROR COUNT*)
(*RETURNED BY SOURCE PROGRAM SCANNER INSYMBOL:*)
(**********************************************)
SY: SYMBOL; (*LAST SYMBOL*)
OP: OPERATOR; (*CLASSIFICATION OF LAST SYMBOL*)
VAL: VALU; (*VALUE OF LAST CONSTANT*)
LNGTH: INTEGER; (*LENGTH OF LAST STRING CONSTANT*)
ID: ALPHA ; (*LAST IDENTIFIER (POSSIBLY TRUNCATED)*)
KK: 1..IDLNGTH; (*NR OF CHARS IN LAST IDENTIFIER*)
CH: CHAR; (*LAST CHARACTER READ*)
EOL: BOOLEAN; (*END OF LINE FLAG*)
(*COUNTERS:*)
(***********)
CHCNT, (*CHARACTER COUNTER*) (*PEG*)
CHCNTMAX, (*MAX LINE LENGTH*) (*PEG*)
CURLINLEN: 0..STD_CHCNTMAX; (*LENGTH OF CURRENT LINE + 1*) (*PEG*)
LC,IC,OLDIC: ADDRRANGE ; (*DATA LOCATION AND INSTRUCTION COUNTER*)
# LINECOUNT ,MXDATASZE: INTEGER;
(*SWITCHES:*)
(***********)
DP, (*DECLARATION PART*)
PRTERR, (*TO ALLOW FORWARD REFERENCES IN PTR TYPE
(*DECLARATION BY SUPPRESSING ERROR MSG*)
ENDFLG, (*SY=END*)
# DOTFLG, (*ONE DOT ALREADY SEEN*)
# ASSIGN,PACKDATA, (*ASSIGNMENT GOING ON, WORD ALIGN FLAG *)
# LIST,PRCODE,PRTABLES,PRTIC,
# SEQNUMBERS,DEBUG,BYTEON,
# (*OUTPUT OPTIONS FOR
# --> SOURCE PROGRAM LISTING
# --> PRINTING SYMBOLIC CODE
# --> DISPLAYING IDENT AND STRUCT TABLES
# --> LAST 8 COLS. OF INPUT INTERPRETED
AS SEQUENCE NUMBERS-- PEG
# --> PRINT INST_CNTR, PROCEDURE OPTION*)
#
# ASSEMBLE,ASMVERB,EBCDFLG, XLINK,
# SAVEREGS,SAVEFPRS,GET_STAT: BOOLEAN;
# (*POST PROCESSOR OPTIONS*)
#
(*POINTERS:*)
(***********)
INTPTR,REALPTR,CHARPTR,BOOLPTR,
NILPTR,TEXTPTR,ALFAPTR: STP; (*POINTERS TO ENTRIES OF STANDARD IDS*)
UTYPPTR,UCSTPTR,UVARPTR,
UFLDPTR,UPRCPTR,UFCTPTR, (*POINTERS TO ENTRIES FOR UNDECLARED IDS*)
FWPTR: CTP; (*HEAD OF CHAIN OF FORW DECL TYPE IDS*)
FEXTFILEP: EXTFILEP; (*HEAD OF CHAIN OF EXTERNAL FILES*)
GLOBTESTP: TESTP; (*LAST TESTPOINTER*)
(*BOOKKEEPING OF DECLARATION LEVELS:*)
(************************************)
LEVEL: LEVRANGE; (*CURRENT STATIC LEVEL*)
DISX, (*LEVEL OF LAST ID SEARCHED BY SEARCHID*)
TOP: DISPRANGE; (*TOP OF DISPLAY*)
DISPLAY: (*WHERE: MEANS:*)
ARRAY [DISPRANGE] OF
PACKED RECORD (*=BLCK: ID IS VARIABLE ID*)
FNAME: CTP; FLABEL: LBP; (*=CREC: ID IS FIELD ID IN RECORD WITH*)
CASE OCCUR: WHERE OF (* CONSTANT ADDRESS*)
CREC: (CLEV: LEVRANGE; (*=VREC: ID IS FIELD ID IN RECORD WITH*)
CDSPL: ADDRRANGE);(* VARIABLE ADDRESS*)
VREC: (VDSPL: ADDRRANGE)
END; (* --> PROCEDURE WITHSTATEMENT*)
(*ERROR MESSAGES:*)
(*****************)
ERRINX: 0..10; (*NR OF ERRORS IN CURRENT SOURCE LINE*)
ERRLIST:
ARRAY [1..10] OF
PACKED RECORD POS: 1..81;
NMR: 1..400
END;
(*EXPRESSION COMPILATION:*)
(*************************)
GATTR: ATTR; (*DESCRIBES THE EXPR CURRENTLY COMPILED*)
NULL_SET: SETREP;
(*STRUCTURED CONSTANTS:*)
(***********************)
# ATOZ, NUMERIC,
# ALPHANUMERIC : SET OF CHAR ; (*VALID ALPHA-NUMERICS*)
# LINEBUF: ARRAY[1..STD_CHCNTMAX] OF CHAR ; (*CURRENT LINE BUFFER*) (*PEG*)
# SEQFLD: ARRAY [1..8] OF CHAR ; (*SEQ. NUM. FIELD OF INPUT LINE, $M+ ONLY*)
CONSTBEGSYS,SIMPTYPEBEGSYS,TYPEBEGSYS,BLOCKBEGSYS,SELECTSYS,FACBEGSYS,
STATBEGSYS,TYPEDELS: SETOFSYS;
## NXTFILBUF : ADDRRANGE ;
### CALL_LVL : ARRAY[BOOLEAN] OF INTEGER ;
RW: ARRAY [1..NRSW(*NR. OF RES. WORDS*)] OF ALPHA;
FRW: ARRAY [1..14] OF 1..NRSW_P1 (*NR. OF RES. WORDS + 1*); (*PEG*)
RSY: ARRAY [1..NRSW(*NR. OF RES. WORDS*)] OF SYMBOL;
"SSY: ARRAY ['+'..';'] OF SYMBOL;" (*XSL10*)
SSY: ARRAY [' '..'←'] OF SYMBOL; (*XSL10*)
ROP: ARRAY [1..NRSW(*NR. OF RES. WORDS*)] OF OPERATOR;
"SOP: ARRAY ['+'..';'] OF OPERATOR;" (*XSL10*)
SOP: ARRAY [' '..'←'] OF OPERATOR; (*XSL10*)
NA: ARRAY [1..45] OF ALPHA;
MN: ARRAY [0..OPMAX] OF PACKED ARRAY [1..4] OF CHAR;
SNA: ARRAY [1..32] OF PACKED ARRAY [1..3] OF CHAR;
# INTLABEL,PROCLAB: LABELRNG ; MXINT10: INTEGER;
"CTR" CTRCNT : CTRRANGE ;
"CTR" CTRCNTLBL : LABELRNG ;
"CTR" CTROPTION : BOOLEAN;
"CTR" " FIRSTCTR : BOOLEAN; "
"S1" FPRM1, SPRM1, RPRM1 : ADDRRANGE ; REGS_FULL: BOOLEAN ;
(*-------------------------------------------------------------------------*)
(** ERREXIT PRINTERROR FILL_BUFFER LISTLINE SKIP_E_DIRECTORY ENDOFLINE ERROR **)
PROCEDURE ERREXIT (CODE : INTEGER); (*XSL10*)
BEGIN (*XSL10*)
WRITELN(OUTPUT,'**** ERREXIT CALLED WITH CODE =',CODE); (*XSL10*)
(* EXIT(CODE) *) (*X10S1*)
HALT (*XSL10*) (*X10S1*)
END; (*XSL10*)
PROCEDURE PRINTERROR ;
VAR LASTPOS,FREEPOS,CURRPOS,CURRNMR,F,K: INTEGER;
# BEGIN
# IF NOT LIST THEN
# BEGIN
# IF SEQNUMBERS THEN WRITE(OUTPUT, SEQFLD:9) ELSE WRITELN(OUTPUT,LINECOUNT:9) ;
# WRITELN(OUTPUT, ' ':13, LINEBUF:80) ;
# END ;
# (*OUTPUT ERROR MESSAGES*)
# WRITE(OUTPUT,'****':12, ' ':10) ;
# LASTPOS := 0; FREEPOS := 1;
# FOR K := 1 TO ERRINX DO
# BEGIN
# WITH ERRLIST[K] DO
# BEGIN CURRPOS := POS; CURRNMR := NMR END;
# IF CURRPOS = LASTPOS THEN WRITE(OUTPUT,',')
# ELSE
# BEGIN
# WHILE FREEPOS < CURRPOS DO
# BEGIN WRITE(OUTPUT,' '); FREEPOS := FREEPOS + 1 END;
# WRITE(OUTPUT,'↑');
# LASTPOS := CURRPOS
# END;
# IF CURRNMR < 10 THEN F := 1
# ELSE IF CURRNMR < 100 THEN F := 2
# ELSE F := 3;
# WRITE(OUTPUT,CURRNMR:F);
# FREEPOS := FREEPOS + F + 1
# END;
# WRITELN(OUTPUT); ERRINX := 0 ; PRCODE := FALSE ;
# END (*PRINTERROR*) ;
PROCEDURE FILL_BUFFER; (*PEG...*)
VAR I: 0..STD_CHCNTMAX;
BEGIN
I := 0;
WHILE (I < CHCNTMAX - 1) AND NOT EOLN(INPUT) DO
BEGIN
I := I + 1;
READ(INPUT,LINEBUF[I]);
END;
I := I + 1;
LINEBUF[I] := ' ';
CURLINLEN := I + 1;
READLN(INPUT);
END; (*FILL_BUFFER*) (*...PEG*)
PROCEDURE LISTLINE; (*PEG...*)
VAR I: 0..STD_CHCNTMAX;
BEGIN
IF SEQNUMBERS THEN WRITE(OUTPUT, SEQFLD:9)
ELSE WRITE(OUTPUT,LINECOUNT: 9) ;
IF DP THEN WRITE(OUTPUT,LC:8) ELSE WRITE(OUTPUT,IC:8);
WRITE(OUTPUT,LEVEL:3,') ') ;
FOR I := 1 TO CURLINLEN - 1 DO WRITE(OUTPUT, LINEBUF[I]);
WRITELN(OUTPUT);
END; (*LISTLINE*) (*...PEG*)
PROCEDURE SKIP_E_DIRECTORY; (*XSL10...*)
VAR
I: INTEGER; CH: CHAR;
FIRST_SEVEN: PACKED ARRAY[1..7] OF CHAR;
BEGIN
FILL_BUFFER;
FOR I:=1 TO 7 DO
FIRST_SEVEN[I] := LINEBUF[I];
IF FIRST_SEVEN = 'COMMENT' THEN
BEGIN
REPEAT
READ(INPUT,CH);
UNTIL CH = ';';
READLN(INPUT);
FILL_BUFFER;
END;
LISTLINE;
END; (*SKIP_E_DIR*) (*...XSL10*)
PROCEDURE ENDOFLINE ;
VAR I: 0..STD_CHCNTMAX; (*PEG*) (*XSL10*)
BEGIN IF ERRINX > 0 THEN PRINTERROR ; (*XSL10*)
IF SEQNUMBERS THEN (*PEG*)
FOR I := CHCNTMAX - 8 TO CHCNTMAX - 1 (*PEG*)
DO LINEBUF[I] := ' '; (*PEG*) (*XSL10*)
FILL_BUFFER; (*PEG*)
# IF SEQNUMBERS THEN (*PEG*)
# FOR I := 1 TO 8 DO (*PEG*)
# BEGIN SEQFLD[I] := LINEBUF[CHCNTMAX - (9-I)] ; (*PEG*)
LINEBUF[CHCNTMAX - (9-I)] := ' ' END ; (*PEG*)
# LINECOUNT := LINECOUNT+1 ;
IF LIST THEN LISTLINE; (*PEG*)
CHCNT := 0
END (*ENDOFLINE*) ;
PROCEDURE ERROR(FERRNR: INTEGER);
BEGIN
IF ERRINX >= 9 THEN
BEGIN ERRLIST[10].NMR := 255; ERRINX := 10 END
ELSE
BEGIN ERRINX := ERRINX + 1;
ERRLIST[ERRINX].NMR := FERRNR
END;
ERRLIST[ERRINX].POS := CHCNT ;
# ERRORCOUNT := ERRORCOUNT+1 ;
END (*ERROR*) ;
(** INSYMBOL SKIPBLNK NEXTCH OPTIONS **)
PROCEDURE INSYMBOL;
(*READ NEXT BASIC SYMBOL OF SOURCE PROGRAM AND RETURN ITS
DESCRIPTION IN THE GLOBAL VARIABLES SY, OP, ID, VAL AND LNGTH*)
LABEL 1,2,3;
VAR I,K: INTEGER;
DIGIT: PACKED ARRAY [1..REALLNGTH] OF CHAR;
STRING: PACKED ARRAY [1..STRGLNGTH] OF CHAR;
LVP: CSP;TEST: BOOLEAN;
#
#
# PROCEDURE SKIPBLNK;
# (* SKIP BLANKS, ENDOFLINE, AND (OPTIONAL) MARGIN, SKIPS AT LEAST ONE CHAR *)
#
# BEGIN
# REPEAT
# IF EOL THEN
# BEGIN
# IF EOF(INPUT) THEN
# BEGIN WRITELN(OUTPUT,'**** EOF ENCOUNTERED':24) ;
# ERREXIT(ERRORCOUNT+1) ; (*XSL10*)
# END ;
# ENDOFLINE ;
# END;
# REPEAT
CHCNT := CHCNT+1 ;
UNTIL (LINEBUF[CHCNT] <> ' ') OR (CHCNT = CURLINLEN); (*PEG*)
# EOL := CHCNT = CURLINLEN; (*PEG*)
# UNTIL NOT EOL ;
# CH := LINEBUF[CHCNT] ;
EOL := (CHCNT + 1) = CURLINLEN; (*PEG*)
# END (*SKIPBLNK*) ;
PROCEDURE NEXTCH;
BEGIN
IF EOL THEN
BEGIN
IF EOF(INPUT) THEN
BEGIN WRITELN(OUTPUT,'**** EOF ENCOUNTERED':24) ;
ERREXIT(ERRORCOUNT+1) ; (*XSL10*)
END ;
ENDOFLINE ;
END;
CHCNT := CHCNT+1 ;
CH := LINEBUF[CHCNT] ;
EOL := CHCNT + 1 = CURLINLEN; (*PEG*)
END;
PROCEDURE OPTIONS;
BEGIN
REPEAT NEXTCH;
IF CH <> '*' THEN
BEGIN
IF CH = 'T' THEN
BEGIN NEXTCH; PRTABLES := CH = '+' END
ELSE
IF CH = 'L' THEN
BEGIN NEXTCH; LIST := CH = '+';
" IF NOT LIST THEN WRITELN(OUTPUT) "
END
ELSE
IF CH = 'C' THEN
BEGIN NEXTCH; PRCODE := CH = '+' END
ELSE
IF CH = 'E' THEN
# BEGIN NEXTCH ;
# EBCDFLG := CH = '+' ;
# END
# ELSE
# IF CH = 'A' THEN
# BEGIN NEXTCH ; ASSEMBLE := CH ='+' END
# ELSE
# IF CH='M' THEN
# BEGIN
NEXTCH; (*PEG...*)
CHCNTMAX := 0;
WHILE (CH IN NUMERIC) DO
BEGIN
CHCNTMAX := CHCNTMAX*10 + (ORD(CH)-ORD('0'));
NEXTCH;
END;
IF (CHCNTMAX = 0) OR (CHCNTMAX < 8)
OR (CHCNTMAX > STD_CHCNTMAX - 1) THEN
CHCNTMAX := DEF_CHCNTMAX
ELSE CHCNTMAX := CHCNTMAX + 1;
CHCNT := CHCNT - 1; (*BACK UP ONE CHAR*)
END
ELSE
IF CH='N' THEN
BEGIN
NEXTCH;
SEQNUMBERS := CH = '+';
END (*...PEG*)
# ELSE
# IF CH = 'S' THEN
# BEGIN NEXTCH ; SAVEREGS := CH <> '-' END
# ELSE
# IF CH = 'F' THEN
# BEGIN NEXTCH ; SAVEFPRS := CH <> '-' ;
# END
# ELSE
# IF CH = 'D' THEN
# BEGIN NEXTCH ; DEBUG := CH <> '-' END
# ELSE
# IF CH = 'P' THEN
# BEGIN NEXTCH ; PACKDATA := CH = '+' ;
# (*LCW IF PACKDATA THEN MXDATASZE := INTSIZE *)
# (*LCW ELSE MXDATASZE := REALSIZE ; *)
# END
# ELSE
# IF CH = 'B' THEN
# BEGIN NEXTCH ; BYTEON := CH = '+' ;
# DEBUG := BYTEON ;
# END
# ELSE
# IF CH = 'V' THEN
# BEGIN NEXTCH ; ASMVERB := CH ='+' END
# ELSE
# IF CH = 'U' THEN
# BEGIN NEXTCH ; GET_STAT := CH = '+' END
# ELSE
# IF CH = 'X' THEN
# BEGIN NEXTCH; XLINK := CH = '+' END
# ELSE IF CH = 'K' THEN
# BEGIN NEXTCH;
"CTR" CTROPTION := CH = '+' ;
"CTR" IF CTROPTION THEN REWRITE(QRD) ;
# END ;
NEXTCH
END
UNTIL CH <> ','
END (*OPTIONS*) ;
BEGIN (*INSYMBOL*)
1:
# IF CH = ' ' THEN SKIPBLNK ;
CASE CH OF
'A','B','C','D','E','F','G','H','I',
'J','K','L','M','N','O','P','Q','R',
'S','T','U','V','W','X','Y','Z':
# BEGIN K := 0 ; ID := BLANK12 ;
REPEAT
IF K < IDLNGTH THEN
BEGIN K := K + 1; ID[K] := CH END ;
NEXTCH
# UNTIL NOT(CH IN ALPHANUMERIC) ;
" IF K >= KK THEN KK := K
ELSE
REPEAT ID[KK] := ' '; KK := KK - 1
UNTIL KK = K; "
FOR I := FRW[K] TO FRW[K+1] - 1 DO
IF RW[I] = ID THEN
BEGIN SY := RSY[I]; OP := ROP[I]; GOTO 2 END;
SY := IDENT; OP := NOOP;
2: END;
'0','1','2','3','4','5','6','7','8','9':
BEGIN OP := NOOP; I := 0;
REPEAT I := I+1; IF I<= DIGMAX THEN DIGIT[I] := CH; NEXTCH
UNTIL NOT (CH IN NUMERIC) ;
IF (CH = '.') OR (CH = 'E') THEN
BEGIN
K := I;
IF CH = '.' THEN
BEGIN K := K+1; IF K <= DIGMAX THEN DIGIT[K] := CH;
NEXTCH;
# IF CH = '.' THEN BEGIN DOTFLG := TRUE; GOTO 3 END;
IF NOT (CH IN NUMERIC) THEN
ERROR(201)
ELSE
REPEAT K := K + 1;
IF K <= DIGMAX THEN DIGIT[K] := CH; NEXTCH
UNTIL NOT (CH IN NUMERIC)
END;
IF CH = 'E' THEN
BEGIN K := K+1; IF K <= DIGMAX THEN DIGIT[K] := CH;
NEXTCH;
IF (CH = '+') OR (CH ='-') THEN
BEGIN K := K+1; IF K <= DIGMAX THEN DIGIT[K] := CH;
NEXTCH
END;
IF NOT (CH IN NUMERIC) THEN
ERROR(201)
ELSE
REPEAT K := K+1;
IF K <= DIGMAX THEN DIGIT[K] := CH; NEXTCH
UNTIL NOT (CH IN NUMERIC)
END;
NEW(LVP,REEL); SY:= REALCONST; "LVP↑.CCLASS := REEL;"
WITH LVP↑ DO
BEGIN FOR I := 1 TO REALLNGTH DO RVAL[I] := ' ';
IF K <= DIGMAX THEN
FOR I := 2 TO K + 1 DO RVAL[I] := DIGIT[I-1]
ELSE BEGIN ERROR(203); RVAL[2] := '0';
RVAL[3] := '.'; RVAL[4] := '0'
END
END;
VAL.VALP := LVP
END
ELSE
3: BEGIN
IF I > DIGMAX THEN BEGIN ERROR(203); VAL.IVAL := 0 END
ELSE
WITH VAL DO
BEGIN IVAL := 0;
FOR K := 1 TO I DO
BEGIN
IF IVAL <= MXINT10 THEN
IVAL := IVAL*10 + (ORD(DIGIT[K])-ORD('0'))
ELSE BEGIN ERROR(203); IVAL := 0 END
END;
SY := INTCONST
END
END
END;
'''':
BEGIN LNGTH := 0; SY := STRINGCONST; OP := NOOP;
REPEAT
REPEAT NEXTCH; LNGTH := LNGTH + 1;
IF LNGTH <= STRGLNGTH THEN STRING[LNGTH] := CH
UNTIL (EOL) OR (CH = '''');
IF EOL THEN ERROR(202) ELSE NEXTCH
UNTIL CH <> '''';
LNGTH := LNGTH - 1; (*NOW LNGTH = NR OF CHARS IN STRING*)
IF LNGTH = 1 THEN VAL.IVAL := ORD(STRING[1])-CHARDIF (*CHARDIF*)
ELSE
BEGIN NEW(LVP,STRG); "LVP↑.CCLASS:=STRG;"
IF LNGTH > STRGLNGTH THEN
BEGIN ERROR(398); LNGTH := STRGLNGTH END;
WITH LVP↑ DO
BEGIN SLNGTH := LNGTH;
FOR I := 1 TO LNGTH DO SVAL[I] := STRING[I]
END;
VAL.VALP := LVP
END
END;
':':
BEGIN OP := NOOP; NEXTCH;
IF CH = '=' THEN
BEGIN SY := BECOMES; NEXTCH END
ELSE SY := COLON
END;
'.':
BEGIN OP := NOOP;
IF NOT ENDFLG THEN
BEGIN
IF NOT DOTFLG THEN NEXTCH;
IF CH = '.' THEN
BEGIN SY := DOTDOT; DOTFLG := FALSE ; NEXTCH END
ELSE SY := PERIOD;
END
ELSE SY := PERIOD;
END;
'<':
BEGIN NEXTCH; SY := RELOP;
IF CH = '=' THEN
BEGIN OP := LEOP; NEXTCH END
ELSE
IF CH = '>' THEN
BEGIN OP := NEOP; NEXTCH END
ELSE OP := LTOP
END;
'>':
BEGIN NEXTCH; SY := RELOP;
IF CH = '=' THEN
BEGIN OP := GEOP; NEXTCH END
ELSE OP := GTOP
END;
'(':
BEGIN NEXTCH;
IF CH = '*' THEN
BEGIN NEXTCH;
IF CH = '$' THEN OPTIONS;
REPEAT
WHILE CH <> '*' DO NEXTCH;
NEXTCH
UNTIL CH = ')';
NEXTCH; GOTO 1
END ;
# IF CH = '/' THEN
# BEGIN SY := LBRACK ; OP := NOOP ;
# NEXTCH
# END
ELSE BEGIN SY := LPARENT; OP := NOOP END
END;
# '[',']', (*XSL10*)
# '*','+','-','%',
# '=','/',')','&',"'|','¬'," (*XSL10*)
# '!','?',',',';','↑','$':
BEGIN SY := SSY[CH]; OP := SOP[CH];
# IF CH = '/' THEN
# BEGIN NEXTCH ;
# IF CH =')' THEN
# BEGIN SY := RBRACK ; OP := NOOP ;
# NEXTCH ;
# END
# END
# ELSE NEXTCH
END;
# '"':
# BEGIN REPEAT NEXTCH UNTIL CH = '"' ;
# NEXTCH ; GOTO 1 ;
# END ;
# '#':
# BEGIN NEXTCH ; GOTO 1 END ;
# '@','←': (*XSL10*)
# BEGIN SY := OTHERSY; OP := NOOP; ERROR(398) ; NEXTCH END
END (*CASE*)
END (*INSYMBOL*) ;
(** ENTERID SEARCHSECTION SEARCHID GETBOUNDS **)
PROCEDURE ENTERID(FCP: CTP);
(*ENTER ID POINTED AT BY FCP INTO THE NAME-TABLE,
WHICH ON EACH DECLARATION LEVEL IS ORGANISED AS
AN UNBALANCED BINARY TREE*)
VAR NAM: ALPHA; LCP, LCP1: CTP; LLEFT: BOOLEAN;
BEGIN NAM := FCP↑.NAME;
LCP := DISPLAY[TOP].FNAME;
IF LCP = NIL THEN
DISPLAY[TOP].FNAME := FCP
ELSE
BEGIN
REPEAT LCP1 := LCP;
IF LCP↑.NAME = NAM THEN (*NAME CONFLICT, FOLLOW RIGHT LINK*)
BEGIN ERROR(101); LCP := LCP↑.RLINK; LLEFT := FALSE END
ELSE
IF LCP↑.NAME < NAM THEN
BEGIN LCP := LCP↑.RLINK; LLEFT := FALSE END
ELSE BEGIN LCP := LCP↑.LLINK; LLEFT := TRUE END
UNTIL LCP = NIL;
IF LLEFT THEN LCP1↑.LLINK := FCP ELSE LCP1↑.RLINK := FCP
END;
FCP↑.LLINK := NIL; FCP↑.RLINK := NIL
END (*ENTERID*) ;
PROCEDURE SEARCHSECTION(FCP: CTP; VAR FCP1: CTP);
(*TO FIND RECORD FIELDS AND FORWARD DECLARED PROCEDURE ID'S
--> PROCEDURE PROCEDUREDECLARATION
--> PROCEDURE SELECTOR*)
LABEL 1;
BEGIN
WHILE FCP <> NIL DO
IF FCP↑.NAME = ID THEN GOTO 1
ELSE IF FCP↑.NAME < ID THEN FCP := FCP↑.RLINK
ELSE FCP := FCP↑.LLINK;
1: FCP1 := FCP
END (*SEARCHSECTION*) ;
PROCEDURE SEARCHID(FIDCLS: SETOFIDS; VAR FCP: CTP);
LABEL 1;
VAR LCP: CTP;
BEGIN
FOR DISX := TOP DOWNTO 0 DO
BEGIN LCP := DISPLAY[DISX].FNAME;
WHILE LCP <> NIL DO
IF LCP↑.NAME = ID THEN
IF LCP↑.KLASS IN FIDCLS THEN GOTO 1
ELSE
BEGIN IF PRTERR THEN ERROR(103);
LCP := LCP↑.RLINK
END
ELSE
IF LCP↑.NAME < ID THEN
LCP := LCP↑.RLINK
ELSE LCP := LCP↑.LLINK
END;
(*SEARCH NOT SUCCSESSFUL; SUPPRESS ERROR MESSAGE IN CASE
OF FORWARD REFERENCED TYPE ID IN POINTER TYPE DEFINITION
--> PROCEDURE SIMPLETYPE*)
IF PRTERR THEN
BEGIN ERROR(104);
(*TO AVOID RETURNING NIL, REFERENCE AN ENTRY
FOR AN UNDECLARED ID OF APPROPRIATE CLASS
--> PROCEDURE ENTERUNDECL*)
IF TYPES IN FIDCLS THEN LCP := UTYPPTR
ELSE
IF VARS IN FIDCLS THEN LCP := UVARPTR
ELSE
IF FIELD IN FIDCLS THEN LCP := UFLDPTR
ELSE
IF KONST IN FIDCLS THEN LCP := UCSTPTR
ELSE
IF PROC IN FIDCLS THEN LCP := UPRCPTR
ELSE LCP := UFCTPTR;
END;
1: FCP := LCP
END (*SEARCHID*) ;
PROCEDURE GETBOUNDS(FSP: STP; VAR FMIN,FMAX: INTEGER);
(*GET INTERNAL BOUNDS OF SUBRANGE OR SCALAR TYPE*)
(*ASSUME (FSP <> NIL) AND (FSP↑.FORM <= SUBRANGE) AND (FSP <> INTPTR)
AND NOT COMPTYPES(REALPTR,FSP)*)
BEGIN
WITH FSP↑ DO
IF FORM = SUBRANGE THEN
BEGIN FMIN := MIN.IVAL; FMAX := MAX.IVAL END
ELSE
BEGIN FMIN := 0;
# IF FSP = CHARPTR THEN IF BYTEON THEN FMAX := 255 ELSE FMAX := 63
ELSE
IF (FORM = SCALAR) AND (FSP↑.FCONST <> NIL) THEN
FMAX := FSP↑.FCONST↑.VALUES.IVAL
ELSE FMAX := 0
END
END (*GETBOUNDS*) ;
(** PRINTTABLES MARKER MARKCTP MARKSTP MARKCTP FOLLOWCTP FOLLOWSTP **)
" PROCEDURE PRINTTABLES(FB: BOOLEAN);
(*PRINT DATA STRUCTURE AND NAME TABLE*)
VAR I, LIM: DISPRANGE;
PROCEDURE MARKER;
(*MARK DATA STRUCTURE ENTRIES TO AVOID MULTIPLE PRINTOUT*)
VAR I: INTEGER;
PROCEDURE MARKCTP(FP: CTP); FORWARD;
PROCEDURE MARKSTP(FP: STP);
(*MARK DATA STRUCTURES, PREVENT CYCLES*)
BEGIN
IF FP <> NIL THEN
WITH FP↑ DO
BEGIN MARKED := TRUE;
CASE FORM OF
SCALAR: ;
SUBRANGE: MARKSTP(RANGETYPE);
POINTER: (*DON'T MARK ELTYPE: CYCLE POSSIBLE; WILL BE MARKED
ANYWAY, IF FP = TRUE*) ;
POWER: MARKSTP(ELSET) ;
ARRAYS: BEGIN MARKSTP(AELTYPE); MARKSTP(INXTYPE) END;
RECORDS: BEGIN MARKCTP(FSTFLD); MARKSTP(RECVAR) END;
FILES: MARKSTP(FILTYPE);
TAGFLD: MARKSTP(FSTVAR);
VARIANT: BEGIN MARKSTP(NXTVAR); MARKSTP(SUBVAR) END
END (*CASE*)
END (*WITH*)
END (*MARKSTP*);
PROCEDURE MARKCTP;
BEGIN
IF FP <> NIL THEN
WITH FP↑ DO
BEGIN MARKCTP(LLINK); MARKCTP(RLINK);
MARKSTP(IDTYPE)
END
END (*MARKCTP*);
BEGIN (*MARK*)
FOR I := TOP DOWNTO LIM DO
MARKCTP(DISPLAY[I].FNAME)
END (*MARK*);
PROCEDURE FOLLOWCTP(FP: CTP); FORWARD;
PROCEDURE FOLLOWSTP(FP: STP);
BEGIN
IF FP <> NIL THEN
WITH FP↑ DO
IF MARKED THEN
BEGIN MARKED := FALSE; WRITE(OUTPUT,' ':4,ORD(FP):6,SIZE:10);
CASE FORM OF
SCALAR: BEGIN WRITE(OUTPUT,'SCALAR':10);
IF SCALKIND = STANDARD THEN
WRITE(OUTPUT,'STANDARD ':10)
ELSE WRITE(OUTPUT,'DECLARED ':10, ORD(FCONST):8);
WRITELN(OUTPUT)
END;
SUBRANGE:BEGIN
WRITE(OUTPUT,'SUBRANGE ':10,' ':4,ORD(RANGETYPE):6);
IF RANGETYPE <> REALPTR THEN
WRITE(OUTPUT,MIN.IVAL,MAX.IVAL)
ELSE
IF (MIN.VALP <> NIL) AND (MAX.VALP <> NIL) THEN
WRITE(OUTPUT,' ',MIN.VALP↑.RVAL:9,
' ',MAX.VALP↑.RVAL:9);
WRITELN(OUTPUT); FOLLOWSTP(RANGETYPE);
END;
POINTER: WRITELN(OUTPUT,'POINTER':10,' ':4,ORD(ELTYPE):6);
POWER: BEGIN WRITELN(OUTPUT,'SET':10,' ':4,ORD(ELSET):6);
FOLLOWSTP(ELSET)
END;
ARRAYS: BEGIN
WRITELN(OUTPUT,'ARRAY':10,' ':4,ORD(AELTYPE):6,' ':4,
ORD(INXTYPE):6);
FOLLOWSTP(AELTYPE); FOLLOWSTP(INXTYPE)
END;
RECORDS: BEGIN
WRITELN(OUTPUT,'RECORD':10,' ':4,ORD(FSTFLD):6,' ':4,
ORD(RECVAR):6); FOLLOWCTP(FSTFLD);
FOLLOWSTP(RECVAR)
END;
FILES: BEGIN WRITE(OUTPUT,'FILE':10,' ':4,ORD(FILTYPE):6);
FOLLOWSTP(FILTYPE)
END;
TAGFLD: BEGIN WRITELN(OUTPUT,'TAGFLD':10,' ':4,ORD(TAGFIELDP):6,
' ':4,ORD(FSTVAR):6);
FOLLOWSTP(FSTVAR)
END;
VARIANT: BEGIN WRITELN(OUTPUT,'VARIANT':10,' ':4,ORD(NXTVAR):6,
' ':4,ORD(SUBVAR):6,VARVAL.IVAL);
FOLLOWSTP(NXTVAR); FOLLOWSTP(SUBVAR)
END
END (*CASE*)
END (*IF MARKED*)
END (*FOLLOWSTP*);
(** FOLLOWCTP GENLABEL PRNTSYMBL PRNTVAR PRNTTYPE PRNTVAR **)
PROCEDURE FOLLOWCTP;
VAR I: INTEGER;
BEGIN
IF FP <> NIL THEN
WITH FP↑ DO
BEGIN WRITE(OUTPUT,' ':4,ORD(FP):6,' ',NAME:9,' ':4,ORD(LLINK):6,
' ':4,ORD(RLINK):6,' ':4,ORD(IDTYPE):6);
CASE KLASS OF
TYPES: WRITE(OUTPUT,'TYPE':10);
KONST: BEGIN WRITE(OUTPUT,'CONSTANT ':10,' ':4,ORD(NEXT):6);
IF IDTYPE <> NIL THEN
IF IDTYPE = REALPTR THEN
BEGIN
IF VALUES.VALP <> NIL THEN
WRITE(OUTPUT,' ',VALUES.VALP↑.RVAL:9)
END
ELSE
IF IDTYPE↑.FORM = ARRAYS THEN (*STRINGCONST*)
BEGIN
IF VALUES.VALP <> NIL THEN
BEGIN WRITE(OUTPUT,' ');
WITH VALUES.VALP↑ DO
FOR I := 1 TO SLNGTH DO
WRITE(OUTPUT,SVAL[I])
END
END
ELSE WRITE(OUTPUT,VALUES.IVAL)
END;
VARS: BEGIN WRITE(OUTPUT,'VARIABLE ':10);
IF VKIND = ACTUAL THEN WRITE(OUTPUT,'ACTUAL':10)
ELSE WRITE(OUTPUT,'FORMAL':10);
WRITE(OUTPUT,' ':4,ORD(NEXT):6,VLEV,' ':4,VADDR:6 );
END;
FIELD: WRITE(OUTPUT,'FIELD':10,' ':4,ORD(NEXT):6,' ':4,FLDADDR:6);
PROC,
FUNC: BEGIN
IF KLASS = PROC THEN WRITE(OUTPUT,'PROCEDURE':10)
ELSE WRITE(OUTPUT,'FUNCTION ':10);
IF PFDECKIND = STANDARD THEN
WRITE(OUTPUT,'STANDARD ':10,
KEY:10)
ELSE
BEGIN WRITE(OUTPUT,'DECLARED ':10, ORD(NEXT):8);
WRITE(OUTPUT,PFLEV,' ':4,PFNAME:6);
IF PFKIND = ACTUAL THEN
BEGIN WRITE(OUTPUT,'ACTUAL':10);
IF FWDECL THEN WRITE(OUTPUT,'FORWARD':10)
ELSE WRITE(OUTPUT,'NOTFORWARD':10);
IF EXTRN THEN WRITE(OUTPUT,'EXTRN':10)
ELSE WRITE(OUTPUT,'NOT EXTRN':10);
END
ELSE WRITE(OUTPUT,'FORMAL':10)
END
END
END (*CASE*);
WRITELN(OUTPUT); FOLLOWCTP(LLINK); FOLLOWCTP(RLINK);
FOLLOWSTP(IDTYPE)
END (*WITH*)
END (*FOLLOWCTP*);
BEGIN (*PRINTTABLES*)
WRITELN(OUTPUT); WRITELN(OUTPUT); WRITELN(OUTPUT);
IF FB THEN LIM := 0
ELSE BEGIN LIM := TOP; WRITE(OUTPUT,' LOCAL') END;
WRITELN(OUTPUT,' TABLES '); WRITELN(OUTPUT);
MARKER;
FOR I := TOP DOWNTO LIM DO
FOLLOWCTP(DISPLAY[I].FNAME);
WRITELN(OUTPUT);
IF NOT EOL THEN WRITE(OUTPUT,' ':CHCNT+16)
END (*PRINTTABLES*); "
PROCEDURE GENLABEL(VAR NXTLAB: INTEGER);
BEGIN INTLABEL := INTLABEL + 1;
NXTLAB := INTLABEL
END (*GENLABEL*);
(* THE FOLLOWING WRITES ENTRIES INTO SYMTBL FOR USE BY DUMP PROGRAM *)
"E"
PROCEDURE PRNTSYMBL(LCP:CTP);
VAR LINELN:INTEGER; (* CURRENT OUTPUT LINE LENGTH *)
PROCEDURE PRNTVAR(VRP:CTP; VAR LINELN:INTEGER); FORWARD;
PROCEDURE PRNTTYPE(TYPP:STP; VAR LINELN:INTEGER);
VAR VP:CTP;
BEGIN
IF (LINELN+3) >= 80 THEN BEGIN WRITELN(SYMTBL);
WRITE(SYMTBL,' '); LINELN := 0; END
ELSE LINELN := LINELN+3;
IF TYPP=INTPTR THEN WRITE(SYMTBL,'I; ')
ELSE IF TYPP=REALPTR THEN WRITE(SYMTBL,'R; ')
ELSE IF TYPP=BOOLPTR THEN WRITE(SYMTBL,'B; ')
ELSE IF TYPP=CHARPTR THEN WRITE(SYMTBL,'C; ')
ELSE CASE TYPP↑.FORM OF
SCALAR: WRITE(SYMTBL,'L; ');
POINTER: WRITE(SYMTBL,'P; ');
POWER: WRITE(SYMTBL,'S; ');
FILES: WRITE(SYMTBL,'F; ');
RECORDS: BEGIN WRITE(SYMTBL,'D ');
VP := TYPP↑.FSTFLD;
WHILE VP <> NIL DO BEGIN PRNTVAR(VP, LINELN);
VP := VP↑.NEXT; END;
IF (LINELN+2) >= 80 THEN BEGIN WRITELN(SYMTBL);
WRITE(SYMTBL,' '); LINELN := 0; END
ELSE LINELN := LINELN+2;
WRITE(SYMTBL,'; ');
END;
ARRAYS: BEGIN WRITE(SYMTBL,'A ');
IF (LINELN+26) >= 80 THEN BEGIN WRITELN(SYMTBL);
WRITE(SYMTBL,' '); LINELN := 0 END
ELSE LINELN := LINELN+26;
WRITE(SYMTBL,TYPP↑.INXTYPE↑.MIN.IVAL,' ',
TYPP↑.INXTYPE↑.MAX.IVAL,' ');
PRNTTYPE(TYPP↑.AELTYPE, LINELN);
END;
END;
END; (* PRNTTYPE *)
PROCEDURE PRNTVAR;
BEGIN
IF (LINELN+IDLNGTH+1) >= 80 THEN BEGIN WRITELN(SYMTBL);
WRITE(SYMTBL,' '); LINELN := 0; END
ELSE LINELN := LINELN+IDLNGTH+1;
WRITE(SYMTBL,VRP↑.NAME,' ');
PRNTTYPE(VRP↑.IDTYPE, LINELN);
END;
BEGIN (* PRNTSYMBL *)
CASE LCP↑.KLASS OF
VARS: BEGIN
WRITE(SYMTBL,LCP↑.VADDR,' ',LCP↑.NAME,' ');
LINELN := IDLNGTH+12;
PRNTTYPE(LCP↑.IDTYPE, LINELN);
END;
PROC,FUNC: BEGIN
WRITE(SYMTBL,'% ',LCP↑.NAME,' ',LCP↑.PFNAME);
WHILE LCP↑.NEXT <> NIL DO BEGIN
PRNTSYMBL(LCP↑.NEXT); LCP := LCP↑.NEXT; END;
END;
TYPES,KONST,FIELD: ;
END;
WRITELN(SYMTBL);
END; (* PRNTSYMBL *)
"E"
(** SET_IN BUILD_SET **)
(* SET_IN performs the function of the set IN operator for the structured
representation of large sets. Its first parameter is the scalar to be
tested for inclusion in the set, which is the second parameter. setch*)
function SET_IN(SET_EL: SET_EL_TYP; PSET: SETREP): boolean; (*setch*)
var INDEX: SETREP_INDEX;
begin
INDEX := SET_EL div HOST_SET_SIZE; (*figure which real set to use*)
SET_EL := SET_EL mod HOST_SET_SIZE; (*figure correct offset*)
if SET_EL in PSET[INDEX] then
SET_IN := true
else
SET_IN := false;
end (*SET_IN*);
procedure BUILD_SET(SET_EL: SET_EL_TYP; var S: SETREP); (*setch*)
(*Add a scalar to a structured representation of a large set.*)
var INDEX: SETREP_INDEX;
begin
INDEX := SET_EL div HOST_SET_SIZE;
SET_EL := SET_EL mod HOST_SET_SIZE;
S[INDEX] := S[INDEX]+[SET_EL];
end (*BUILD_SET*);
(** BLOCK SKIP ALIGN CONSTANT **)
PROCEDURE BLOCK(FSYS: SETOFSYS; FSY: SYMBOL; FPROCP: CTP);
# VAR LSY: SYMBOL; TEST: BOOLEAN; SEGSIZE: INTEGER ;
PROCEDURE SKIP(FSYS: SETOFSYS);
(*SKIP INPUT STRING UNTIL RELEVANT SYMBOL FOUND*)
BEGIN
WHILE NOT(SY IN FSYS) DO
BEGIN
INSYMBOL
END ;
END (*SKIP*) ;
#
# PROCEDURE ALIGN(VAR Q:ADDRRANGE; P: ADDRRANGE) ;
#
# VAR I : INTEGER ;
#
# BEGIN
# IF P >= MXDATASZE THEN P := MXDATASZE (*LCW*)
# ELSE IF P >= INTSIZE THEN P := INTSIZE
# ELSE IF P <= 0 THEN IF ERRORCOUNT = 0 THEN ERROR(500) ;
# IF P >= INTSIZE THEN
# BEGIN I:= Q MOD P ; IF I > 0 THEN Q := Q+(P-I) END ;
# END (*ALIGN*) ;
PROCEDURE CONSTANT(FSYS: SETOFSYS; VAR FSP: STP; VAR FVALU: VALU);
VAR LSP: STP; LCP: CTP; SIGN: (NONE,POS,NEG);
LVP: CSP; I: 2..REALLNGTH;
BEGIN LSP := NIL; FVALU.IVAL := 0;
IF NOT(SY IN CONSTBEGSYS) THEN
BEGIN ERROR(50); SKIP(FSYS+CONSTBEGSYS) END;
IF SY IN CONSTBEGSYS THEN
BEGIN
IF SY = STRINGCONST THEN
BEGIN
IF LNGTH = 1 THEN LSP := CHARPTR
ELSE
BEGIN
NEW(LSP,ARRAYS);
WITH LSP↑ DO
BEGIN AELTYPE := CHARPTR; INXTYPE := NIL;
SIZE := LNGTH*CHARSIZE; FORM := ARRAYS
END
END;
FVALU := VAL; INSYMBOL
END
ELSE
BEGIN
SIGN := NONE;
IF (SY = ADDOP) AND (OP IN [PLUS,MINUS]) THEN
BEGIN IF OP = PLUS THEN SIGN := POS ELSE SIGN := NEG;
INSYMBOL
END;
IF SY = IDENT THEN
BEGIN SEARCHID([KONST],LCP);
WITH LCP↑ DO
BEGIN LSP := IDTYPE; FVALU := VALUES END;
IF SIGN <> NONE THEN
IF LSP = INTPTR THEN
BEGIN IF SIGN = NEG THEN FVALU.IVAL := -FVALU.IVAL END
ELSE
IF LSP = REALPTR THEN
BEGIN
IF SIGN = NEG THEN
BEGIN NEW(LVP,REEL);
IF FVALU.VALP↑.RVAL[1] = '-' THEN
LVP↑.RVAL[1] := '+'
ELSE LVP↑.RVAL[1] := '-';
FOR I := 2 TO REALLNGTH DO
LVP↑.RVAL[I] := FVALU.VALP↑.RVAL[I];
FVALU.VALP := LVP;
END
END
ELSE ERROR(105);
INSYMBOL;
END
ELSE
IF SY = INTCONST THEN
BEGIN IF SIGN = NEG THEN VAL.IVAL := -VAL.IVAL;
LSP := INTPTR; FVALU := VAL; INSYMBOL
END
ELSE
IF SY = REALCONST THEN
BEGIN IF SIGN = NEG THEN VAL.VALP↑.RVAL[1] := '-';
LSP := REALPTR; FVALU := VAL; INSYMBOL
END
ELSE
BEGIN ERROR(106); SKIP(FSYS) END
END;
IF NOT (SY IN FSYS) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END;
FSP := LSP
END (*CONSTANT*) ;
(** COMPTYPES STRING **)
FUNCTION COMPTYPES(FSP1,FSP2: STP) : BOOLEAN;
(*DECIDE WHETHER STRUCTURES POINTED AT BY FSP1 AND FSP2 ARE COMPATIBLE*)
VAR NXT1,NXT2: CTP; COMP: BOOLEAN;
LTESTP1,LTESTP2 : TESTP;
BEGIN
IF FSP1 = FSP2 THEN COMPTYPES := TRUE
ELSE
IF (FSP1 <> NIL) AND (FSP2 <> NIL) THEN
IF FSP1↑.FORM = FSP2↑.FORM THEN
CASE FSP1↑.FORM OF
SCALAR:
COMPTYPES := FALSE;
(* IDENTICAL SCALARS DECLARED ON DIFFERENT LEVELS ARE
NOT RECOGNIZED TO BE COMPATIBLE*)
SUBRANGE:
COMPTYPES := COMPTYPES(FSP1↑.RANGETYPE,FSP2↑.RANGETYPE);
POINTER:
BEGIN
COMP := FALSE; LTESTP1 := GLOBTESTP;
LTESTP2 := GLOBTESTP;
WHILE LTESTP1 <> NIL DO
WITH LTESTP1↑ DO
BEGIN
IF (ELT1 = FSP1↑.ELTYPE) AND
(ELT2 = FSP2↑.ELTYPE) THEN COMP := TRUE;
LTESTP1 := LASTTESTP
END;
IF NOT COMP THEN
BEGIN NEW(LTESTP1);
WITH LTESTP1↑ DO
BEGIN ELT1 := FSP1↑.ELTYPE;
ELT2 := FSP2↑.ELTYPE;
LASTTESTP := GLOBTESTP
END;
GLOBTESTP := LTESTP1;
COMP := COMPTYPES(FSP1↑.ELTYPE,FSP2↑.ELTYPE)
END;
COMPTYPES := COMP; GLOBTESTP := LTESTP2
END;
POWER:
COMPTYPES := COMPTYPES(FSP1↑.ELSET,FSP2↑.ELSET);
ARRAYS:
COMPTYPES := COMPTYPES(FSP1↑.AELTYPE,FSP2↑.AELTYPE)
AND (FSP1↑.SIZE = FSP2↑.SIZE);
(*ALTERNATIVES: -- ADD A THIRD BOOLEAN TERM: INDEXTYPE MUST
BE COMPATIBLE.
-- ADD A FOURTH BOOLEAN TERM: LOWBOUNDS MUST
BE THE SAME*)
RECORDS:
BEGIN NXT1 := FSP1↑.FSTFLD; NXT2 := FSP2↑.FSTFLD; COMP:=TRUE;
WHILE (NXT1 <> NIL) AND (NXT2 <> NIL) DO
BEGIN COMP:=COMP AND COMPTYPES(NXT1↑.IDTYPE,NXT2↑.IDTYPE);
NXT1 := NXT1↑.NEXT; NXT2 := NXT2↑.NEXT
END;
COMPTYPES := COMP AND (NXT1 = NIL) AND (NXT2 = NIL)
AND(FSP1↑.RECVAR = NIL)AND(FSP2↑.RECVAR = NIL)
END;
(*IDENTICAL RECORDS ARE RECOGNIZED TO BE COMPATIBLE
IFF NO VARIANTS OCCUR*)
FILES:
COMPTYPES := COMPTYPES(FSP1↑.FILTYPE,FSP2↑.FILTYPE)
END (*CASE*)
ELSE (*FSP1↑.FORM <> FSP2↑.FORM*)
IF FSP1↑.FORM = SUBRANGE THEN
COMPTYPES := COMPTYPES(FSP1↑.RANGETYPE,FSP2)
ELSE
IF FSP2↑.FORM = SUBRANGE THEN
COMPTYPES := COMPTYPES(FSP1,FSP2↑.RANGETYPE)
ELSE COMPTYPES := FALSE
ELSE COMPTYPES := TRUE
END (*COMPTYPES*) ;
FUNCTION STRING(FSP: STP) : BOOLEAN;
BEGIN STRING := FALSE;
IF FSP <> NIL THEN
IF FSP↑.FORM = ARRAYS THEN
# STRING := COMPTYPES(FSP↑.AELTYPE,CHARPTR)
END (*STRING*) ;
(** TYP SIMPLETYPE **)
PROCEDURE TYP(FSYS: SETOFSYS; VAR FSP: STP; VAR FSIZE: ADDRRANGE);
VAR LSP,LSP1,LSP2: STP; OLDTOP: DISPRANGE; LCP: CTP;
LSIZE,DISPL: ADDRRANGE; LMIN,LMAX: INTEGER; ALNFCT : 1..8 ;
PROCEDURE SIMPLETYPE(FSYS:SETOFSYS; VAR FSP:STP"; VAR FSIZE:ADDRRANGE");
VAR LSP,LSP1: STP; LCP,LCP1: CTP; TTOP: DISPRANGE;
LCNT: INTEGER; LVALU: VALU;
BEGIN FSIZE := 1;
IF NOT (SY IN SIMPTYPEBEGSYS) THEN
BEGIN ERROR(1); SKIP(FSYS + SIMPTYPEBEGSYS) END;
IF SY IN SIMPTYPEBEGSYS THEN
BEGIN
IF SY = LPARENT THEN
BEGIN TTOP := TOP; (*DECL. CONSTS LOCAL TO INNERMOST BLOCK*)
WHILE DISPLAY[TOP].OCCUR <> BLCK DO TOP := TOP - 1;
NEW(LSP,SCALAR,DECLARED);
WITH LSP↑ DO
BEGIN SIZE := INTSIZE; FORM := SCALAR;
SCALKIND := DECLARED
END;
LCP1 := NIL; LCNT := 0;
REPEAT INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(LCP,KONST);
WITH LCP↑ DO
BEGIN NAME := ID; IDTYPE := LSP; NEXT := LCP1;
VALUES.IVAL := LCNT; KLASS := KONST
END;
ENTERID(LCP);
LCNT := LCNT + 1;
LCP1 := LCP; INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + [COMMA,RPARENT]) THEN
BEGIN ERROR(6); SKIP(FSYS + [COMMA,RPARENT]) END
UNTIL SY <> COMMA;
# IF PACKDATA THEN
# IF LCNT < 256 THEN LSP↑.SIZE := CHARSIZE ;
# LSP↑.ALN := LSP↑.SIZE ;
LSP↑.FCONST := LCP1; TOP := TTOP;
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END
ELSE
BEGIN
IF SY = IDENT THEN
BEGIN SEARCHID([TYPES,KONST],LCP);
INSYMBOL;
IF LCP↑.KLASS = KONST THEN
BEGIN NEW(LSP,SUBRANGE);
WITH LSP↑, LCP↑ DO
BEGIN RANGETYPE := IDTYPE; FORM := SUBRANGE;
IF STRING(RANGETYPE) THEN
BEGIN ERROR(148); RANGETYPE := NIL END;
# MIN := VALUES; SIZE := IDTYPE↑.SIZE
END;
## # IF SY = DOTDOT THEN INSYMBOL ELSE ERROR(5);
CONSTANT(FSYS,LSP1,LVALU);
LSP↑.MAX := LVALU;
# IF PACKDATA THEN
# IF LVALU.IVAL < 256 THEN
# IF LSP↑.MIN.IVAL >= 0 THEN LSP↑.SIZE := CHARSIZE ;
# LSP↑.ALN := LSP↑.SIZE ;
IF LSP↑.RANGETYPE <> LSP1 THEN ERROR(107)
END
ELSE
BEGIN LSP := LCP↑.IDTYPE;
# " IF LSP <> NIL THEN FSIZE := LSP↑.SIZE "
END
END (*SY = IDENT*)
ELSE
BEGIN NEW(LSP,SUBRANGE); LSP↑.FORM := SUBRANGE;
CONSTANT(FSYS + [DOTDOT],LSP1,LVALU);
IF STRING(LSP1) THEN
BEGIN ERROR(148); LSP1 := NIL END;
WITH LSP↑ DO
# BEGIN RANGETYPE:=LSP1; MIN:=LVALU; SIZE:=INTSIZE;
# IF LSP1 <> NIL THEN SIZE := LSP1↑.SIZE ;
# END;
## # IF SY = DOTDOT THEN INSYMBOL ELSE ERROR(5);
CONSTANT(FSYS,LSP1,LVALU);
LSP↑.MAX := LVALU;
# IF PACKDATA THEN
# IF LVALU.IVAL < 256 THEN
# IF LSP↑.MIN.IVAL >= 0 THEN LSP↑.SIZE := CHARSIZE ;
# LSP↑.ALN := LSP↑.SIZE ;
IF LSP↑.RANGETYPE <> LSP1 THEN ERROR(107)
END;
IF LSP <> NIL THEN
WITH LSP↑ DO
IF FORM = SUBRANGE THEN
IF RANGETYPE <> NIL THEN
IF RANGETYPE = REALPTR THEN ERROR(398)
ELSE
IF MIN.IVAL > MAX.IVAL THEN ERROR(102)
END;
FSP := LSP;
IF NOT (SY IN FSYS) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END
ELSE FSP := NIL
END (*SIMPLETYPE*) ;
(** FIELDLIST **)
PROCEDURE FIELDLIST(FSYS: SETOFSYS; VAR FRECVAR: STP;VAR RECALN: ALNRNG);
VAR LCP,LCP1,NXT,NXT1: CTP; LSP,LSP1,LSP2,LSP3,LSP4: STP;
# MINSIZE,MAXSIZE,LSIZE: ADDRRANGE; LVALU: VALU; LALNFCT : ALNRNG ;
# BEGIN NXT1 := NIL; LSP := NIL; RECALN := 1 ;
IF NOT (SY IN FSYS+[IDENT,CASESY]) THEN
BEGIN ERROR(19); SKIP(FSYS + [IDENT,CASESY]) END;
WHILE SY = IDENT DO
BEGIN NXT := NXT1;
REPEAT
IF SY = IDENT THEN
BEGIN NEW(LCP,FIELD);
WITH LCP↑ DO
BEGIN NAME := ID; IDTYPE := NIL; NEXT := NXT;
KLASS := FIELD
END;
NXT := LCP;
ENTERID(LCP);
INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN [COMMA,COLON]) THEN
BEGIN ERROR(6); SKIP(FSYS + [COMMA,COLON,SEMICOLON,CASESY])
END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
TYP(FSYS + [CASESY,SEMICOLON],LSP,LSIZE);
# LALNFCT := 1 ; IF LSP <> NIL THEN LALNFCT := LSP↑.ALN ;
WHILE NXT <> NXT1 DO
WITH NXT↑ DO
# BEGIN IDTYPE := LSP; ALIGN(DISPL,LALNFCT) ; FLDADDR := DISPL;
NXT := NEXT; DISPL := DISPL + LSIZE
END;
# IF LALNFCT > RECALN THEN RECALN := LSP↑.ALN ;
NXT1 := LCP;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
# IF NOT (SY IN [IDENT,CASESY,ENDSY]) THEN (* IGNOR EXTRA ; *)
BEGIN ERROR(19); SKIP(FSYS + [IDENT,CASESY]) END
END
END (*WHILE*);
NXT := NIL;
WHILE NXT1 <> NIL DO
WITH NXT1↑ DO
BEGIN LCP := NEXT; NEXT := NXT; NXT := NXT1; NXT1 := LCP END;
IF SY = CASESY THEN
BEGIN NEW(LSP,TAGFLD);
WITH LSP↑ DO
BEGIN TAGFIELDP := NIL; FSTVAR := NIL; FORM:=TAGFLD END;
FRECVAR := LSP;
INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(LCP,FIELD);
WITH LCP↑ DO
BEGIN NAME := ID; IDTYPE := NIL; KLASS:=FIELD;
# NEXT := NIL ; (*FLDADDR WILL BE SET WHEN TYPE IS KNOWN*)
END;
"TAG" PRTERR := FALSE ; SEARCHID([TYPES],LCP1) ; PRTERR := TRUE ;
"TAG" IF LCP1 = NIL THEN BEGIN (*EXPLICIT TAG FIELD *)
# ENTERID(LCP); INSYMBOL ;
# IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
# IF SY <> IDENT THEN
# BEGIN ERROR(2); SKIP(FSYS + [OFSY,LPARENT]) END
"TAG" ; END (* IF LCP1 = NIL *)
# ELSE (* NO EXPLICT TAG FIELD *)
"TAG" LCP↑.NAME := BLANK12 ;
BEGIN SEARCHID([TYPES],LCP1);
LSP1 := LCP1↑.IDTYPE;
IF LSP1 <> NIL THEN
WITH LSP1↑ DO
# BEGIN
"TAG" IF LCP↑.NAME <> BLANK12 THEN BEGIN
# ALIGN(DISPL,ALN) ;
# IF ALN > RECALN THEN RECALN := ALN ;
# LCP↑.FLDADDR := DISPL ; DISPL := DISPL + SIZE;
"TAG" END (* LCP↑.NAME <> BLANK12 *) ;
IF (FORM <= SUBRANGE) OR STRING(LSP1) THEN
BEGIN IF COMPTYPES(REALPTR,LSP1) THEN ERROR(109)
ELSE IF STRING(LSP1) THEN ERROR(398);
LCP↑.IDTYPE := LSP1; LSP↑.TAGFIELDP := LCP;
END
ELSE ERROR(110);
END (* WITH LSP1↑ DO *) ;
INSYMBOL;
END
END
ELSE BEGIN ERROR(2); SKIP(FSYS + [OFSY,LPARENT]) END;
# LSP↑.SIZE := DISPL;
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8);
LSP1 := NIL; MINSIZE := DISPL; MAXSIZE := DISPL;
REPEAT LSP2 := NIL;
REPEAT CONSTANT(FSYS + [COMMA,COLON,LPARENT],LSP3,LVALU);
IF LSP↑.TAGFIELDP <> NIL THEN
IF NOT COMPTYPES(LSP↑.TAGFIELDP↑.IDTYPE,LSP3)THEN ERROR(111);
NEW(LSP3,VARIANT);
WITH LSP3↑ DO
BEGIN NXTVAR := LSP1; SUBVAR := LSP2; VARVAL := LVALU;
FORM := VARIANT
END;
LSP1 := LSP3; LSP2 := LSP3;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
FIELDLIST(FSYS + [RPARENT,SEMICOLON],LSP2,LALNFCT);
# IF LALNFCT > RECALN THEN RECALN := LALNFCT ;
IF DISPL > MAXSIZE THEN MAXSIZE := DISPL;
WHILE LSP3 <> NIL DO
BEGIN LSP4 := LSP3↑.SUBVAR; LSP3↑.SUBVAR := LSP2;
LSP3↑.SIZE := DISPL;
LSP3 := LSP4
END;
IF SY = RPARENT THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + [SEMICOLON]) THEN
BEGIN ERROR(6); SKIP(FSYS + [SEMICOLON]) END
END
ELSE ERROR(4);
TEST := SY <> SEMICOLON;
IF NOT TEST THEN
BEGIN DISPL := MINSIZE;
# INSYMBOL ; TEST := SY = ENDSY ; (* IGNORE EXTRA ;*)
END
UNTIL TEST;
DISPL := MAXSIZE;
LSP↑.FSTVAR := LSP1;
END
ELSE FRECVAR := NIL
END (*FIELDLIST*) ;
BEGIN (*TYP*)
IF NOT (SY IN TYPEBEGSYS) THEN
BEGIN ERROR(10); SKIP(FSYS + TYPEBEGSYS) END;
IF SY IN TYPEBEGSYS THEN
BEGIN
IF SY IN SIMPTYPEBEGSYS THEN SIMPLETYPE(FSYS,FSP",FSIZE")
ELSE
(*↑*) IF SY = ARROW THEN
BEGIN NEW(LSP,POINTER); FSP := LSP;
WITH LSP↑ DO
BEGIN ELTYPE := NIL;
# SIZE := PTRSIZE; ALN := PTRSIZE ; FORM:=POINTER
END;
INSYMBOL;
IF SY = IDENT THEN
BEGIN PRTERR := FALSE; (*NO ERROR IF SEARCH NOT SUCCESSFUL*)
SEARCHID([TYPES],LCP); PRTERR := TRUE;
IF LCP = NIL THEN (*FORWARD REFERENCED TYPE ID*)
BEGIN NEW(LCP,TYPES);
WITH LCP↑ DO
BEGIN NAME := ID; IDTYPE := LSP;
NEXT := FWPTR; KLASS := TYPES
END;
FWPTR := LCP
END
ELSE
BEGIN
IF LCP↑.IDTYPE <> NIL THEN
IF LCP↑.IDTYPE↑.FORM = FILES THEN ERROR(108)
ELSE LSP↑.ELTYPE := LCP↑.IDTYPE
END;
INSYMBOL;
END
ELSE ERROR(2);
END
ELSE
BEGIN
IF SY = PACKEDSY THEN
BEGIN INSYMBOL;
IF NOT (SY IN TYPEDELS) THEN
BEGIN
ERROR(10); SKIP(FSYS + TYPEDELS)
END
END;
(*ARRAY*) IF SY = ARRAYSY THEN
BEGIN INSYMBOL;
IF SY = LBRACK THEN INSYMBOL ELSE ERROR(11);
LSP1 := NIL;
REPEAT NEW(LSP,ARRAYS);
WITH LSP↑ DO
BEGIN AELTYPE := LSP1; INXTYPE := NIL; FORM:=ARRAYS END;
LSP1 := LSP;
SIMPLETYPE(FSYS + [COMMA,RBRACK,OFSY],LSP2",LSIZE");
# " LSP1↑.SIZE := LSIZE ; NOT USED "
IF LSP2 <> NIL THEN
IF LSP2↑.FORM <= SUBRANGE THEN
BEGIN
IF LSP2 = REALPTR THEN
BEGIN ERROR(109); LSP2 := NIL END
ELSE
IF LSP2 = INTPTR THEN
BEGIN ERROR(149); LSP2 := NIL END;
LSP↑.INXTYPE := LSP2
END
ELSE BEGIN ERROR(113); LSP2 := NIL END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12);
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8);
# TYP(FSYS,LSP,LSIZE); ALIGN(LSIZE,LSP↑.ALN) ;
REPEAT
WITH LSP1↑ DO
BEGIN LSP2 := AELTYPE; AELTYPE := LSP;
IF INXTYPE <> NIL THEN
BEGIN GETBOUNDS(INXTYPE,LMIN,LMAX);
LSIZE := LSIZE*(LMAX - LMIN + 1);
SIZE := LSIZE ; ALN := LSP↑.ALN (*PROPAG. ALN*) ;
END
END;
LSP := LSP1; LSP1 := LSP2
UNTIL LSP1 = NIL
END
ELSE
(*RECORD*) IF SY = RECORDSY THEN
BEGIN INSYMBOL;
OLDTOP := TOP;
IF TOP < DISPLIMIT THEN
BEGIN TOP := TOP + 1;
WITH DISPLAY[TOP] DO
BEGIN FNAME := NIL;
FLABEL := NIL;
OCCUR := REC
END
END
ELSE ERROR(250);
DISPL := 0;
FIELDLIST(FSYS-[SEMICOLON]+[ENDSY],LSP1,ALNFCT);
NEW(LSP,RECORDS);
WITH LSP↑ DO
BEGIN FSTFLD := DISPLAY[TOP].FNAME;
RECVAR := LSP1; SIZE := DISPL;
FORM := RECORDS ; ALN := ALNFCT ;
END;
TOP := OLDTOP;
IF SY = ENDSY THEN INSYMBOL ELSE ERROR(13)
END
ELSE
(*SET*) IF SY = SETSY THEN
BEGIN INSYMBOL;
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8);
SIMPLETYPE(FSYS,LSP1",LSIZE");
IF LSP1 <> NIL THEN
IF LSP1↑.FORM > SUBRANGE THEN
BEGIN ERROR(115); LSP1 := NIL END
ELSE
IF LSP1 = REALPTR THEN ERROR(114)
## ELSE IF LSP1↑.FORM = SUBRANGE THEN
## IF LSP1↑.MAX.IVAL > MAXSETEL THEN ERROR(304);
NEW(LSP,POWER);
WITH LSP↑ DO
BEGIN ELSET:=LSP1;
SIZE:=SETSIZE; ALN := INTSIZE ; FORM:=POWER
END;
END
ELSE
(*FILE*) IF SY = FILESY THEN
# "BEGIN ERROR(398); INSYMBOL; SKIP(FSYS); LSP:= NIL END;"
## BEGIN INSYMBOL ;
## IF SY = OFSY THEN INSYMBOL ELSE ERROR(8) ;
## SIMPLETYPE(FSYS,LSP1",LSIZE") ;
## IF LSP1 = NIL THEN ERROR(398)
## ELSE IF LSP1 <> CHARPTR THEN ERROR(398) ;
## LSP := TEXTPTR ;
## END ;
FSP := LSP
END;
IF NOT (SY IN FSYS) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END
ELSE FSP := NIL;
IF FSP = NIL THEN FSIZE := 1 ELSE FSIZE := FSP↑.SIZE
END (*TYP*) ;
(** LABELDECLARATION CONSTDECLARATION TYPEDECLARATION **)
PROCEDURE LABELDECLARATION;
VAR LLP: LBP; REDEF: BOOLEAN; LBNAME: LABELRNG ;
BEGIN
REPEAT
IF SY = INTCONST THEN
WITH DISPLAY[TOP] DO
BEGIN LLP := FLABEL; REDEF := FALSE;
WHILE (LLP <> NIL) AND NOT REDEF DO
IF LLP↑.LABVAL <> VAL.IVAL THEN
LLP := LLP↑.NEXTLAB
ELSE BEGIN REDEF := TRUE; ERROR(166) END;
IF NOT REDEF THEN
BEGIN NEW(LLP);
WITH LLP↑ DO
BEGIN LABVAL := VAL.IVAL; GENLABEL(LBNAME);
DEFINED := FALSE; NEXTLAB := FLABEL; LABNAME := LBNAME
END;
FLABEL := LLP
END;
INSYMBOL
END
ELSE ERROR(15);
IF NOT ( SY IN FSYS + [COMMA, SEMICOLON] ) THEN
BEGIN ERROR(6); SKIP(FSYS+[COMMA,SEMICOLON]) END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14)
END (* LABELDECLARATION *) ;
PROCEDURE CONSTDECLARATION;
VAR LCP: CTP; LSP: STP; LVALU: VALU;
BEGIN
IF SY <> IDENT THEN
BEGIN ERROR(2); SKIP(FSYS + [IDENT]) END;
WHILE SY = IDENT DO
BEGIN NEW(LCP,KONST);
WITH LCP↑ DO
BEGIN NAME := ID; IDTYPE := NIL; NEXT := NIL; KLASS:=KONST END;
INSYMBOL;
IF (SY = RELOP) AND (OP = EQOP) THEN INSYMBOL ELSE ERROR(16);
CONSTANT(FSYS + [SEMICOLON],LSP,LVALU);
ENTERID(LCP);
LCP↑.IDTYPE := LSP; LCP↑.VALUES := LVALU;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + [IDENT]) THEN
BEGIN ERROR(6); SKIP(FSYS + [IDENT]) END
END
ELSE ERROR(14)
END
END (*CONSTDECLARATION*) ;
PROCEDURE TYPEDECLARATION;
VAR LCP,LCP1,LCP2: CTP; LSP: STP; LSIZE: ADDRRANGE;
BEGIN
IF SY <> IDENT THEN
BEGIN ERROR(2); SKIP(FSYS + [IDENT]) END;
WHILE SY = IDENT DO
BEGIN NEW(LCP,TYPES);
WITH LCP↑ DO
BEGIN NAME := ID; IDTYPE := NIL; KLASS := TYPES END;
INSYMBOL;
IF (SY = RELOP) AND (OP = EQOP) THEN INSYMBOL ELSE ERROR(16);
TYP(FSYS + [SEMICOLON],LSP,LSIZE);
ENTERID(LCP);
LCP↑.IDTYPE := LSP;
(*HAS ANY FORWARD REFERENCE BEEN SATISFIED:*)
LCP1 := FWPTR;
WHILE LCP1 <> NIL DO
BEGIN
IF LCP1↑.NAME = LCP↑.NAME THEN
BEGIN LCP1↑.IDTYPE↑.ELTYPE := LCP↑.IDTYPE;
IF LCP1 <> FWPTR THEN
LCP2↑.NEXT := LCP1↑.NEXT
ELSE FWPTR := LCP1↑.NEXT;
END;
LCP2 := LCP1; LCP1 := LCP1↑.NEXT
END;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + [IDENT]) THEN
BEGIN ERROR(6); SKIP(FSYS + [IDENT]) END
END
ELSE ERROR(14)
END;
IF FWPTR <> NIL THEN
BEGIN ERROR(117); WRITELN(OUTPUT);
REPEAT WRITELN(OUTPUT,' TYPE-ID ',FWPTR↑.NAME);
FWPTR := FWPTR↑.NEXT
UNTIL FWPTR = NIL;
IF NOT EOL THEN WRITE(OUTPUT,' ': CHCNT+16)
END
END (*TYPEDECLARATION*) ;
(** VARDECLARATION **)
PROCEDURE VARDECLARATION;
# VAR LCP,NXT: CTP; LSP: STP; LSIZE: ADDRRANGE; COUNT: 0..100 ;
BEGIN NXT := NIL;
# REPEAT COUNT := 0 ;
REPEAT
IF SY = IDENT THEN
BEGIN NEW(LCP,VARS); COUNT := COUNT+1 ;
WITH LCP↑ DO
BEGIN NAME := ID; NEXT := NXT; KLASS := VARS;
IDTYPE := NIL; VKIND := ACTUAL; VLEV := LEVEL
END;
ENTERID(LCP);
NXT := LCP;
INSYMBOL;
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + [COMMA,COLON] + TYPEDELS) THEN
BEGIN ERROR(6); SKIP(FSYS+[COMMA,COLON,SEMICOLON]+TYPEDELS) END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
TYP(FSYS + [SEMICOLON] + TYPEDELS,LSP,LSIZE);
# IF LSP <> NIL THEN ALIGN(LC,LSP↑.ALN) ;
## IF LSP = TEXTPTR THEN
## BEGIN
## NXTFILBUF := NXTFILBUF+COUNT ; COUNT := 1 ;
## IF NXTFILBUF > LASTFILBUF THEN ERROR(258) ;
## END ;
WHILE NXT <> NIL DO
WITH NXT↑ DO
BEGIN IDTYPE := LSP;
## IF LSP = TEXTPTR THEN (* TEXT FILE DECLARATION *)
## BEGIN "EBCD := EBCDFLG ; EBCDFLG := FALSE ; "
## VADDR := NXTFILBUF-COUNT ; VLEV := 1 ; COUNT := COUNT+1 ;
## END
## ELSE (* OTHER VARIABLE DECLARATION *)
BEGIN VADDR := LC ; LC := LC+LSIZE END ;
"E" PRNTSYMBL(NXT); NXT := NEXT;
END;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + [IDENT]) THEN
BEGIN ERROR(6); SKIP(FSYS + [IDENT]) END
END
ELSE ERROR(14)
UNTIL (SY <> IDENT) AND NOT (SY IN TYPEDELS);
IF FWPTR <> NIL THEN
BEGIN ERROR(117); WRITELN(OUTPUT);
REPEAT WRITELN(OUTPUT,' TYPE-ID ',FWPTR↑.NAME);
FWPTR := FWPTR↑.NEXT
UNTIL FWPTR = NIL;
IF NOT EOL THEN WRITE(OUTPUT,' ': CHCNT+16)
END ;
END (*VARDECLARATION*) ;
(** PROCDECLARATION PARAMETERLIST **)
PROCEDURE PROCDECLARATION(FSY: SYMBOL);
VAR OLDLEV: 0..MAXLEVEL; LSY: SYMBOL; LCP,LCP1: CTP; LSP: STP;
# # FORW: BOOLEAN; OLDTOP: DISPRANGE; PARCNT: INTEGER;
LLC,LCM: ADDRRANGE; LBNAME, OLDLABEL: INTEGER; MARKP: ↑INTEGER;
PROCEDURE PARAMETERLIST(FSY: SETOFSYS; VAR FPAR: CTP);
VAR LCP,LCP1,LCP2,LCP3: CTP; LSP: STP; LKIND: IDKIND;
LLC,LEN : ADDRRANGE; COUNT : INTEGER;
BEGIN LCP1 := NIL ;
"S1" FPRM1 := LC ; RPRM1 := 0 ; REGS_FULL := FALSE ;
IF NOT (SY IN FSY + [LPARENT]) THEN
BEGIN ERROR(7); SKIP(FSYS + FSY + [LPARENT]) END;
IF SY = LPARENT THEN
BEGIN IF FORW THEN ERROR(119);
INSYMBOL;
IF NOT (SY IN [IDENT,VARSY,PROCSY,FUNCSY]) THEN
BEGIN ERROR(7); SKIP(FSYS + [IDENT,RPARENT]) END;
WHILE SY IN [IDENT,VARSY,PROCSY,FUNCSY] DO
BEGIN
IF SY = PROCSY THEN
BEGIN ERROR(398);
REPEAT INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(LCP,PROC,DECLARED,FORMAL);
WITH LCP↑ DO
BEGIN NAME := ID; IDTYPE := NIL; NEXT := LCP1;
PFLEV := LEVEL (*BEWARE OF PARAMETER PROCEDURES*);
KLASS:=PROC;PFDECKIND:=DECLARED;PFKIND:=FORMAL
END;
ENTERID(LCP);
LCP1 := LCP; LC := LC + PTRSIZE;
INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + [COMMA,SEMICOLON,RPARENT]) THEN
BEGIN ERROR(7);SKIP(FSYS+[COMMA,SEMICOLON,RPARENT])END
UNTIL SY <> COMMA
END
ELSE
BEGIN
IF SY = FUNCSY THEN
BEGIN ERROR(398); LCP2 := NIL;
REPEAT INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(LCP,FUNC,DECLARED,FORMAL);
WITH LCP↑ DO
BEGIN NAME := ID; IDTYPE := NIL; NEXT := LCP2;
PFLEV := LEVEL (*BEWARE PARAM FUNCS*);
KLASS:=FUNC;PFDECKIND:=DECLARED;
PFKIND:=FORMAL
END;
ENTERID(LCP);
LCP2 := LCP; LC := LC + PTRSIZE;
INSYMBOL;
END;
IF NOT (SY IN [COMMA,COLON] + FSYS) THEN
BEGIN ERROR(7);SKIP(FSYS+[COMMA,SEMICOLON,RPARENT])
END
UNTIL SY <> COMMA;
IF SY = COLON THEN
BEGIN INSYMBOL;
IF SY = IDENT THEN
BEGIN SEARCHID([TYPES],LCP);
LSP := LCP↑.IDTYPE;
IF LSP <> NIL THEN
IF NOT(LSP↑.FORM IN[SCALAR,SUBRANGE,POINTER])
THEN BEGIN ERROR(120); LSP := NIL END;
LCP3 := LCP2;
WHILE LCP2 <> NIL DO
BEGIN LCP2↑.IDTYPE := LSP; LCP := LCP2;
LCP2 := LCP2↑.NEXT
END;
LCP↑.NEXT := LCP1; LCP1 := LCP3;
INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + [SEMICOLON,RPARENT]) THEN
BEGIN ERROR(7);SKIP(FSYS+[SEMICOLON,RPARENT])END
END
ELSE ERROR(5)
END
ELSE
BEGIN
IF SY = VARSY THEN
BEGIN LKIND := FORMAL; INSYMBOL END
ELSE LKIND := ACTUAL;
LCP2 := NIL;
COUNT := 0;
REPEAT
IF SY = IDENT THEN
BEGIN NEW(LCP,VARS);
WITH LCP↑ DO
BEGIN NAME:=ID; IDTYPE:=NIL; KLASS:=VARS;
VKIND := LKIND; NEXT := LCP2; VLEV := LEVEL;
END;
ENTERID(LCP);
LCP2 := LCP; COUNT := COUNT+1;
INSYMBOL;
END;
IF NOT (SY IN [COMMA,COLON] + FSYS) THEN
BEGIN ERROR(7);SKIP(FSYS+[COMMA,SEMICOLON,RPARENT])
END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN
BEGIN INSYMBOL;
IF SY = IDENT THEN
BEGIN SEARCHID([TYPES],LCP); LEN := PTRSIZE ;
# LSP := LCP↑.IDTYPE;
IF LSP <> NIL THEN
# IF (LKIND=ACTUAL) THEN
# IF LSP↑.FORM <= POWER THEN LEN := LSP↑.SIZE
# ELSE IF LSP↑.FORM = FILES THEN ERROR(121) ;
"S0" " IF LSP↑.FORM = POWER THEN ALIGN(LC,4) "
"S0" " ELSE ALIGN(LC, LEN) ; "
"S1" ALIGN(LEN,MXDATASZE) ; ALIGN(LC,MXDATASZE) ;
LC := LC+COUNT*LEN ; LCP3 := LCP2 ; LLC := LC ;
WHILE LCP2 <> NIL DO
BEGIN LCP := LCP2;
WITH LCP2↑ DO
BEGIN IDTYPE := LSP; LLC := LLC-LEN;
VADDR := LLC;
"S1" IF NOT REGS_FULL THEN
"S1" IF RPRM1+LEN <= REGPRMAREA THEN
"S1" RPRM1 := RPRM1+LEN
"S1" ELSE REGS_FULL := TRUE ;
END;
LCP2 := LCP2↑.NEXT
END;
LCP↑.NEXT := LCP1; LCP1 := LCP3;
INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + [SEMICOLON,RPARENT]) THEN
BEGIN ERROR(7);SKIP(FSYS+[SEMICOLON,RPARENT])END
END
ELSE ERROR(5);
END;
END;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + [IDENT,VARSY,PROCSY,FUNCSY]) THEN
BEGIN ERROR(7); SKIP(FSYS + [IDENT,RPARENT]) END
END
END (*WHILE*) ;
IF SY = RPARENT THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSY + FSYS) THEN
BEGIN ERROR(6); SKIP(FSY + FSYS) END
END
ELSE ERROR(4);
LCP3 := NIL;
(*REVERSE POINTERS AND RESERVE LOCAL CELLS FOR COPIES OF MULTIPLE
VALUES*)
" ALIGN(LC,MXDATASZE) ; " (*NORMALIZE STACK BEFORE ENTRING BLOCK*)
"S1" FPRM1 := LC-FPRM1 ; SPRM1 := LC ;
WHILE LCP1 <> NIL DO
WITH LCP1↑ DO
BEGIN LCP2 := NEXT; NEXT := LCP3;
" IF KLASS = VARS THEN ???"
IF IDTYPE <> NIL THEN
# IF VKIND = ACTUAL THEN
# # " IF FORT THEN ERROR(999)
# # ELSE "
# IF (IDTYPE↑.FORM > POWER) THEN
BEGIN ALIGN(LC,IDTYPE↑.ALN (*OR IDTYPE↑.SIZE*) ) ;
VADDR := LC; LC := LC + IDTYPE↑.SIZE ;
END ;
LCP3 := LCP1; LCP1 := LCP2
END;
"S1" ALIGN(LC, PTRSIZE) ; SPRM1 := LC-SPRM1 ;
FPAR := LCP3
END
ELSE
"S1" BEGIN
FPAR := NIL ;
"S1" FPRM1 := 0 ; SPRM1 := 0 ; RPRM1 := 0 ;
"S1" END ;
END (*PARAMETERLIST*) ;
BEGIN (*PROCDECLARATION*)
LLC := LC; LC := LCAFTMST; (* ADR. OF THE FIRST VAR. IN THIS PROC. *)
# LCP := UPRCPTR ; (* TO INITIALIZE LCP IN CASE ! *)
IF SY = IDENT THEN
BEGIN SEARCHSECTION(DISPLAY[TOP].FNAME,LCP); (*DECIDE WHETHER FORW.*)
IF LCP <> NIL THEN
BEGIN
IF LCP↑.KLASS = PROC THEN
FORW := LCP↑.FWDECL AND(FSY = PROCSY)AND(LCP↑.PFKIND = ACTUAL)
ELSE
IF LCP↑.KLASS = FUNC THEN
FORW:=LCP↑.FWDECL AND(FSY=FUNCSY)AND(LCP↑.PFKIND=ACTUAL)
ELSE FORW := FALSE;
IF NOT FORW THEN ERROR(160)
END
ELSE FORW := FALSE;
IF NOT FORW THEN
BEGIN
IF FSY = PROCSY THEN NEW(LCP,PROC,DECLARED,ACTUAL)
ELSE NEW(LCP,FUNC,DECLARED,ACTUAL);
WITH LCP↑ DO
# BEGIN NAME := ID; IDTYPE := NIL; SAVEFP := FALSE ;
# " EXTRN := FALSE;" PFLEV := LEVEL; PROCLAB := PROCLAB+1 ;
# PFDECKIND := DECLARED; PFKIND := ACTUAL; PFNAME := PROCLAB ;
IF FSY = PROCSY THEN KLASS := PROC
ELSE KLASS := FUNC
END;
ENTERID(LCP)
END
ELSE
BEGIN LCP1 := LCP↑.NEXT;
WHILE LCP1 <> NIL DO
BEGIN
WITH LCP1↑ DO
IF KLASS = VARS THEN
IF IDTYPE <> NIL THEN
BEGIN LCM := VADDR + IDTYPE↑.SIZE;
IF LCM > LC THEN LC := LCM
END;
LCP1 := LCP1↑.NEXT
END
END;
INSYMBOL
END
ELSE ERROR(2);
# OLDLEV := LEVEL; OLDTOP := TOP; OLDLABEL := INTLABEL ; INTLABEL := 0 ;
IF LEVEL < MAXLEVEL THEN LEVEL := LEVEL + 1 ELSE ERROR(251);
IF TOP < DISPLIMIT THEN
BEGIN TOP := TOP + 1;
WITH DISPLAY[TOP] DO
BEGIN
IF FORW THEN FNAME := LCP↑.NEXT
ELSE FNAME := NIL;
FLABEL := NIL;
OCCUR := BLCK
END
END
ELSE ERROR(250);
IF FSY = PROCSY THEN
BEGIN PARAMETERLIST([SEMICOLON],LCP1);
IF NOT FORW THEN LCP↑.NEXT := LCP1
END
ELSE
BEGIN PARAMETERLIST([SEMICOLON,COLON],LCP1);
IF NOT FORW THEN LCP↑.NEXT := LCP1;
IF SY = COLON THEN
BEGIN INSYMBOL;
IF SY = IDENT THEN
BEGIN IF FORW THEN ERROR(122);
SEARCHID([TYPES],LCP1);
LSP := LCP1↑.IDTYPE;
LCP↑.IDTYPE := LSP;
IF LSP <> NIL THEN
# BEGIN
# IF NOT (LSP↑.FORM IN [SCALAR,SUBRANGE,POINTER,POWER]) THEN
# BEGIN ERROR(120); LCP↑.IDTYPE := NIL END;
# IF LSP = REALPTR THEN
# IF SAVEFPRS THEN
# BEGIN LCP1 := LCP↑.NEXT ;
# WHILE LCP1 <> NIL DO
# BEGIN
# LCP1↑.VADDR := LCP1↑.VADDR+FPSAVEAREA ;
# LCP1 := LCP1↑.NEXT ;
# END ;
# LCP↑.SAVEFP := TRUE ; (* SET SAVE FPRS FLAG *)
# LC := LC+FPSAVEAREA ; (* ADJUST LOC. CNTR *)
# END ;
# END (* WITH LSP↑ DO *) ;
INSYMBOL
END
ELSE BEGIN ERROR(2); SKIP(FSYS + [SEMICOLON]) END
END
ELSE
IF NOT FORW THEN ERROR(123)
END;
# # WITH LCP↑ DO
# # BEGIN FWDECL := FALSE ; FRTRN := FALSE ; EXTRN := FALSE END ;
"S1"
"S1" IF NOT FORW THEN
"S1" WITH LCP↑ DO
"S1" BEGIN FPRMSZE := FPRM1 ; RPRMSZE := RPRM1 ; SPRMSZE := SPRM1 END;
"S1"
IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14);
# # IF SY IN [FORWARDSY,FRTRNSY,EXTRNSY] THEN
# # BEGIN
# # IF SY = FORWARDSY THEN
# # IF FORW THEN ERROR(161)
# # ELSE LCP↑.FWDECL := TRUE;
# # IF SY = FRTRNSY THEN
# # BEGIN LCP↑.FRTRN := TRUE ;
# # LCP1 := LCP↑.NEXT ;
# # WHILE LCP1 <> NIL DO
# # BEGIN IF LCP1↑.VKIND <> FORMAL THEN ERROR(7) ;
# # LCP1 := LCP1↑.NEXT ;
# # END ;
# # END (* SY = FRTRNSY *) ;
# # IF SY = EXTRNSY THEN LCP↑.EXTRN := TRUE ;
INSYMBOL;
IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14);
IF NOT (SY IN FSYS) THEN BEGIN ERROR(6); SKIP(FSYS) END
END
ELSE
BEGIN " LCP↑.FWDECL := FALSE; "
"E" PRNTSYMBL(LCP);
NEW(MARKP); (* MARK HEAP FOR BLOCK ENTRY *)
REPEAT BLOCK(FSYS,SEMICOLON,LCP);
IF SY = SEMICOLON THEN
BEGIN "IF PRTABLES THEN PRINTTABLES(FALSE);" INSYMBOL;
IF NOT (SY IN [BEGINSY,PROCSY,FUNCSY]) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END
ELSE ERROR(14)
UNTIL SY IN [BEGINSY,PROCSY,FUNCSY];
(* RELEASE(MARKP);*) (* RETURN LOCAL ENTRIES ON RUNTIME HEAP *) (*X10S1*)
DISPOSE(MARKP); (* RETURN LOCAL ENTRIES ON RUNTIME HEAP *) (*X10S1*)
END;
LEVEL := OLDLEV; TOP := OLDTOP; LC := LLC; INTLABEL := OLDLABEL ;
END (*PROCDECLARATION*) ;
#
(** PROCTYPE BODY PUTIC FLDW GETTYPE **)
# FUNCTION PROCTYPE(FPROCP: CTP): INTEGER ;
#
# BEGIN PROCTYPE := ORD('P') ;
# IF FPROCP <> NIL THEN
# WITH FPROCP↑ DO
# # BEGIN IF FRTRN THEN PROCTYPE := ORD('F') ;
# IF FPROCP↑.IDTYPE <> NIL THEN
# WITH FPROCP↑ DO
# BEGIN
# IF IDTYPE↑.FORM = POWER THEN PROCTYPE := ORD('S')
# ELSE IF IDTYPE = REALPTR THEN
# IF FRTRN THEN PROCTYPE := ORD('Z')
# ELSE PROCTYPE := ORD('R')
# ELSE IF IDTYPE = BOOLPTR THEN
# IF FRTRN THEN PROCTYPE := ORD('X')
# ELSE PROCTYPE := ORD('B')
# ELSE IF IDTYPE↑.FORM = POINTER THEN
# PROCTYPE := ORD('A')
# ELSE IF "(IDTYPE = CHARPTR) OR ((IDTYPE↑.FORM = SUBRANGE)
# AND (IDTYPE↑.RANGETYPE = CHARPTR)) "
# IDTYPE↑.SIZE = 1 THEN PROCTYPE := ORD('C')
# ELSE IF FRTRN THEN PROCTYPE := ORD('Y')
# ELSE PROCTYPE := ORD('I') ;
# END
# END (*WITH FPROCP↑*) ;
# END (*PROCTYPE*) ;
#
PROCEDURE BODY(FSYS: SETOFSYS);
# CONST CIXMAX = 1000;
TYPE OPRANGE = 0..OPMAX;
###
### CALLED_PROC = RECORD
### NAME : ALPHA ;
### LVL : LEVRANGE ;
### CNT : 1..100 ;
### NXT : ↑ CALLED_PROC
### END ;
###
### VAR
### CALL_HEAD, T2_CLIST, T_CLIST : ↑ CALLED_PROC ;
### LOCAL_CALL, (* THIS PROC CALLS A LOCAL PROC *)
### " MOD_TRACE, " (* TRACE VARS BEING MODIFIED *)
### MODIFYING : BOOLEAN ; (*A PROGRAM VAR BEING MODIFIED*)
### VAR_REF, VAR_MOD : INTEGER ; (* # OF VARIABLES ACCESSED/REFERENCED*)
###
LLCP:CTP; SAVEID:ALPHA;
# CSTPTR: CSP;
(*ALLOWS REFERENCING OF NONINTEGER CONSTANTS BY AN INDEX
(INSTEAD OF A POINTER), WHICH CAN BE STORED IN THE P2-FIELD
OF THE INSTRUCTION RECORD UNTIL WRITEOUT.
--> PROCEDURE LOAD, PROCEDURE WRITEOUT*) (*NOT NEEDED IN P_COMP.*)
I, ENTNAME : INTEGER;
LCMAX,LLC1: ADDRRANGE; LCP: CTP;
# LLP: LBP; PROCNAME : ALPHA ;
"CTR" FIRSTLN : INTEGER; CTRNO : CTRRANGE;
PROCEDURE PUTIC;
# BEGIN
IF (IC MOD 10 = 0) THEN
"IF ASSEMBLE AND PRTIC THEN " WRITELN(PRR,' LOC',IC:6) ;
END;
# FUNCTION FLDW(NUM : INTEGER) : INTEGER ;
# VAR FW: 0..20 ;
# BEGIN
# FW := 0 ; IF NUM < 0 THEN FW := 1 ;
# NUM := ABS(NUM) ;
# REPEAT
# NUM := NUM DIV 10 ; FW := FW+1 ;
# UNTIL NUM = 0 ;
# FLDW := FW
# END (*FLDW*);
#
# FUNCTION GETTYPE(OPERAND: STP): INTEGER ;
# BEGIN GETTYPE := ORD('I') ; (* ASSUME INTEGER TYPE *)
# IF OPERAND = NIL THEN BEGIN IF ERRORCOUNT = 0 THEN ERROR(500) END
# ELSE
# IF OPERAND↑.FORM > POWER THEN GETTYPE := ORD('A')
# ELSE
# IF OPERAND↑.FORM = POWER THEN GETTYPE := ORD('S')
# ELSE
# IF OPERAND↑.FORM = POINTER THEN GETTYPE := ORD('A')
# ELSE
# IF OPERAND = REALPTR THEN GETTYPE := ORD('R')
# ELSE
# IF OPERAND = BOOLPTR THEN GETTYPE := ORD('B')
# ELSE
# BEGIN
# IF OPERAND↑.SIZE = CHARSIZE THEN GETTYPE := ORD('C')
# END
# END (*GETTYPE*) ;
#
(** GEN0 GEN1 GEN2 PRINT_SET_OPND **)
PROCEDURE GEN0(FOP: OPRANGE);
BEGIN
IF PRCODE THEN BEGIN PUTIC; WRITELN(PRR,MN[FOP]:4) END;
IC := IC + 1
END (*GEN0*) ;
PROCEDURE GEN1(FOP: OPRANGE; FP2: INTEGER);
VAR K: INTEGER;
BEGIN
IF PRCODE THEN
BEGIN PUTIC; WRITE(PRR,MN[FOP]:4,' '); "LCW 5AUG78"
IF FOP = 30 THEN (*CSP*) WRITELN(PRR,SNA[FP2]:4)
ELSE IF FOP = 37 THEN (*LCA*)
#"LCW 5AUG78" BEGIN WRITE(PRR,'''');
# WITH CSTPTR↑ DO
FOR K := 1 TO SLNGTH DO
# BEGIN WRITE(PRR,SVAL[K]:1);
# IF SVAL[K] = '''' THEN WRITE(PRR,'''')
END ;
WRITELN(PRR,'''')
END
ELSE IF (FOP = 26) OR (FOP = 42)
"S1" OR (FOP = 64) (*PRM*)
THEN (*STO,RET*)
"LCW 5AUG78" WRITELN(PRR,CHR(FP2):1)
"LCW 5AUG78" ELSE WRITELN(PRR,FP2:FLDW(FP2))
END;
IC := IC + 1
END (*GEN1*) ;
PROCEDURE GEN2(FOP: OPRANGE; FP1,FP2: INTEGER);
# VAR I, J, K : INTEGER; "FIRSTMEM : BOOLEAN ;"
PROCEDURE PRINT_SET_OPND(SETPTR: CSP); (*SETCH*)
BEGIN
WRITE(PRR,'S,(');
WITH SETPTR↑ DO
FOR I := 0 TO NUMOFSETOPND - 1 DO
BEGIN J := 0 ; K := MAXSETEL-I*16 ;
FOR K := K DOWNTO K-15 DO
BEGIN J := J*2 ;
IF SET_IN(K,PVAL) THEN J := J+1 ;
END ;
IF I > 0 THEN WRITE(PRR,',') ;
WRITE(PRR, J: FLDW(J) ) ;
END (* FOR I := 0 TO NUMOFSETOPND - 1 *) ;
WRITELN(PRR,')') ;
END (*PRINT_SET_OPND*);
BEGIN (*GEN2*)
IF PRCODE THEN
BEGIN PUTIC; WRITE(PRR,MN[FOP]:4,' ');
CASE FOP OF
22,23,35,39,43: (*DEC,INC,IND,LDO,SRO*)
WRITELN(PRR,CHR(FP1),',',FP2:FLDW(FP2)) ;
45,50: (*CHK,LDA*)
WRITELN(PRR,FP1:FLDW(FP1),',',FP2:FLDW(FP2));
47,48,49,52,53,55: (*EQU..NEQ*)
BEGIN WRITE(PRR,CHR(FP1));
IF FP1 = ORD('M') THEN WRITE(PRR,',',FP2:FLDW(FP2));
WRITELN(PRR)
END;
51: (*LDC*)
CASE FP1 OF
# 0: WRITELN(PRR,'C,''',CHR(FP2):1,'''') ;
1: WRITELN(PRR,'I,',FP2:FLDW(FP2));
2: BEGIN WRITE(PRR,'R,');
# WITH CSTPTR↑ DO
FOR K := 1 TO REALLNGTH DO
IF RVAL[K] <> ' ' THEN WRITE(PRR,RVAL[K]);
WRITELN(PRR)
END;
3: WRITELN(PRR,'B,',FP2:1);
4: WRITELN(PRR,'N');
5: PRINT_SET_OPND(CSTPTR);
# " FIRSTMEM := TRUE ;
# WITH CSTPTR↑ DO
FOR K := 0 TO MAXSETEL DO
# IF K IN PVAL THEN
# BEGIN
# IF FIRSTMEM THEN
# BEGIN WRITE(PRR,K:FLDW(K)) ;
# FIRSTMEM := FALSE
# END
# ELSE WRITE(PRR,',',K:FLDW(K)) ;
# END ;
WRITELN(PRR,')') "
END
END;
END;
IC := IC + 1
END (*GEN2*) ;
(** GEN3 LOAD STORE **)
# PROCEDURE GEN3(FOP: OPRANGE; FP0,FP1,FP2: INTEGER);
# BEGIN
# IF PRCODE THEN
# BEGIN PUTIC; WRITE(PRR,MN[FOP]:4);
"S1" IF FOP = 41 THEN (*MST*)
"S1" WRITE(PRR, FP0:2)
"S1" ELSE
# WRITE(PRR, CHR(FP0):2) ;
# WRITELN(PRR, ',', FP1:FLDW(FP1), ',', FP2:FLDW(FP2)) ;
# END;
# IC := IC + 1
# END (*GEN3*) ;
PROCEDURE LOAD;
BEGIN
WITH GATTR DO
IF TYPTR <> NIL THEN
BEGIN
CASE KIND OF
CST: IF (TYPTR↑.FORM = SCALAR) AND (TYPTR <> REALPTR) THEN
IF TYPTR = BOOLPTR THEN GEN2(51(*LDC*),3,CVAL.IVAL)
ELSE
IF TYPTR = CHARPTR THEN GEN2(51(*LDC*),0,CVAL.IVAL
(*CHARDIF*) +CHARDIF)
ELSE GEN2(51(*LDC*),1,CVAL.IVAL) (*INTEGER*)
ELSE
IF TYPTR = NILPTR THEN GEN2(51(*LDC*),4,0)
ELSE
# BEGIN
# CSTPTR := CVAL.VALP;
IF TYPTR = REALPTR THEN
# GEN2(51(*LDC*),2,0)
ELSE
# GEN2(51(*LDC*),5,0)
END;
VARBL: CASE ACCESS OF
DRCT: " IF VLEVEL <= 1 THEN
GEN2(39(*LDO*),GETTYPE(BTYPE),DPLMT)
# ELSE " GEN3(54(*LOD*),GETTYPE(BTYPE),
" LEVEL-" VLEVEL,DPLMT);
INDRCT: GEN2(35(*IND*),GETTYPE(BTYPE),IDPLMT);
INXD: ERROR(400)
END;
EXPR:
END;
### IF KIND = VARBL THEN VAR_REF := VAR_REF+1 ;
KIND := EXPR
END
END (*LOAD*) ;
PROCEDURE STORE(VAR FATTR: ATTR);
BEGIN
WITH FATTR DO
IF TYPTR <> NIL THEN
CASE ACCESS OF
# DRCT: GEN3(56(*STR*),GETTYPE(BTYPE),VLEVEL,DPLMT);
INDRCT: IF IDPLMT <> 0 THEN ERROR(400)
ELSE GEN1(26(*STO*),GETTYPE(BTYPE));
INXD: ERROR(400)
END
END (*STORE*) ;
(** LOADADDRESS GENFJP GENUJPFJP GENCUPENT MKNAME GENDEF CHKBNDS PUTLABEL CTRGEN CTREMIT **)
PROCEDURE LOADADDRESS;
BEGIN
WITH GATTR DO
IF TYPTR <> NIL THEN
BEGIN
CASE KIND OF
CST: IF STRING(TYPTR) THEN
# BEGIN
# CSTPTR := CVAL.VALP ; GEN1(37(*LCA*),0) ;
# END
ELSE ERROR(400);
VARBL: CASE ACCESS OF
# DRCT: GEN2(50(*LDA*),VLEVEL,DPLMT);
INDRCT: IF IDPLMT <> 0 THEN
GEN2(23(*INC*),ORD('A'),IDPLMT);
INXD: ERROR(400)
END;
EXPR: ERROR(400)
END;
KIND := VARBL; ACCESS := INDRCT; IDPLMT := 0
END
END (*LOADADDRESS*) ;
PROCEDURE GENFJP(FADDR: INTEGER);
BEGIN LOAD;
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> BOOLPTR THEN ERROR(144);
IF PRCODE THEN BEGIN PUTIC;
# WRITELN(PRR,MN[33]:4,' L',FADDR:FLDW(FADDR)) END;
IC := IC + 1
END (*GENFJP*) ;
PROCEDURE GENUJPFJP(FOP: OPRANGE; FP2: INTEGER);
BEGIN
IF PRCODE THEN
# BEGIN PUTIC; WRITELN(PRR, MN[FOP]:4, ' L',FP2:FLDW(FP2)) END;
IC := IC + 1
END (*GENUJPFJP*);
# PROCEDURE GENCUPENT(FOP: OPRANGE;FP0,FP1,FP2: INTEGER;PROCNAME: ALPHA);
# VAR TEMPNAME : ALPHA ;
#
# PROCEDURE MKNAME(VAR ALB: ALPHA; NLB: INTEGER ) ;
# VAR I, J: INTEGER ;
#
# BEGIN
# I := 1 ; J := 8 ;
# IF NOT XLINK THEN J := 5 ;
# REPEAT
# IF ALB[I] = '_' THEN ALB[I] := '$' ; I := I+1 ;
# UNTIL (I > J) OR (ALB[I] = ' ') ;
# IF NOT XLINK THEN
# FOR J := 8 DOWNTO I DO
# BEGIN
# ALB[J] := CHR( ORD('0')+ NLB MOD 10 ) ;
# NLB := NLB DIV 10 ;
# END ;
# END (*MKNAME*) ;
#
# BEGIN (*GENCUPENT*)
# IF PRCODE THEN
# BEGIN PUTIC ; TEMPNAME := PROCNAME ; (*TO PRESERVE FULL NAME*)
# IF FOP = 46 THEN (*CUP*)
# BEGIN MKNAME(TEMPNAME,FP2) ;
# WRITELN(PRR,MN[46],CHR(FP0):2,',',FP1:FLDW(FP1),',',TEMPNAME:8);
# END
# ELSE (*ENT*)
# BEGIN
#(*XSL10*) IF OLDIC = 0 THEN WRITELN(PRR,' BGN ', ORD(ASSEMBLE):1, ',',
#(*XSL10*) ORD(GET_STAT):1, ',', ORD(ASMVERB):1) ;
# IF FPROCP <> NIL THEN MKNAME(TEMPNAME,FP2) ;
# WRITELN(PRR, TEMPNAME:8, MN[32], CHR(FP0):2, ',',
# LEVEL:FLDW(LEVEL), ',L', FP1:FLDW(FP1), ' ',
#(*XSL10*) PROCNAME:IDLNGTH, ORD(SAVEREGS):4,
#(*XSL10*) ORD(SAVEFPRS):2, ORD(DEBUG):2) ;
# END ;
# END ;
# IC := IC + 1
# END (*GENCUPENT*);
#
# PROCEDURE GENDEF(L1, L2: ADDRRANGE ) ;
# BEGIN
# IF PRCODE THEN WRITELN(PRR,'L', L1:FLDW(L1), MN[63(*DEF*)], L2:10);
END (*GENDEF*) ;
#
#
# PROCEDURE CHKBNDS(FSP: STP);
# VAR LMIN,LMAX: INTEGER;
# BEGIN
# IF FSP <> NIL THEN
# IF FSP <> BOOLPTR THEN
# IF FSP <> INTPTR THEN
# IF FSP <> REALPTR THEN
# IF FSP↑.FORM <= POINTER THEN
# BEGIN
# GETBOUNDS(FSP,LMIN,LMAX);
# IF LMAX-LMIN <= 0 THEN
# IF ASSIGN THEN GEN3(45(*CHK*),ORD('A'),-1,0)
# ELSE (* ACCESS *) GEN3(45(*CHK*),ORD('A'),0,0)
# ELSE GEN3(45(*CHK*),ORD('I'),LMIN,LMAX) ;
# END
# END (*CHKBNDS*);
PROCEDURE PUTLABEL(LABNAME: INTEGER);
BEGIN IF PRCODE THEN WRITELN(PRR, 'L', LABNAME:FLDW(LABNAME),' LAB')
END (*PUTLABEL*);
"CTR"
"CTR"
"CTR" FUNCTION CTRGEN : CTRRANGE;
"CTR"
"CTR" BEGIN (* CREATE A UNIQUE STATEMENT COUNTER AND EMIT P-CODE TO INCREME
"CTR" IT *)
"CTR" (* R. L. SITES 3 AUG 77 *)
"CTR" CTRGEN := CTRCNT;
"CTR" IF CTROPTION THEN
"CTR" BEGIN
"CTR" GEN1(39(*CTI*), CTRCNT);
"CTR" CTRCNT := CTRCNT+1;
"CTR" END;
"CTR" END; (* CTRGEN *)
"CTR"
"CTR" PROCEDURE CTREMIT(CTRT:CTRTYPE; CTRNO:CTRRANGE; FLN, MLN, LLN:INTEGER) ;
"CTR"
"CTR"
"CTR" BEGIN (* WRITE AN ENTRY DESCRIBING A STATEMENT COUNTER. *)
"CTR" (* R. L. SITES 3 AUG 77 *)
"CTR" IF CTROPTION THEN
"CTR" BEGIN "" (* IF FIRSTCTR THEN
"CTR" BEGIN WRITELN(CTRTBL , COMPDATE); WRITELN(
"CTR" COMPTIME);
"CTR" FIRSTCTR := FALSE END;
"CTR" WRITELN("CTR"QRR,(((ORD(CTRT)*MAXCTR+CTRNO)*MAXLN+FLN)
"CTR" *MAXLN+MLN)*MAXLN+LLN:20); *) ""
"CTR" WRITELN(QRD, ORD(CTRT):4, CTRNO:6, FLN:7, MLN:7, LLN:7 );
"CTR" END
"CTR" (* PACKING MUST EITHER FIT IN 46 BITS OR MAXCTR,MAXLN MUST BE
"CTR" POWERS OF TWO. *)
"CTR" END; (* CTREMIT *)
"CTR"
(** STATEMENT EXPRESSION SELECTOR **)
PROCEDURE STATEMENT(FSYS: SETOFSYS);
LABEL 1;
VAR LCP: CTP; LLP: LBP; TTOP : DISPRANGE ;
"CTR" CTRNO : CTRRANGE;
PROCEDURE EXPRESSION(FSYS: SETOFSYS); FORWARD;
PROCEDURE SELECTOR(FSYS: SETOFSYS; FCP: CTP);
VAR LATTR: ATTR; LCP: CTP; LMIN,LMAX: INTEGER;
### INDEXING : BOOLEAN ;
BEGIN
### INDEXING := FALSE ;
WITH FCP↑, GATTR DO
BEGIN TYPTR := IDTYPE; KIND := VARBL;
###
### IF GET_STAT THEN
### BEGIN
### IF MODIFYING THEN WRITE(QRR,' #MOD')
### ELSE WRITE(QRR,' #REF') ;
### WRITE(QRR, CHR(GETTYPE("BTYPE" TYPTR)), ' ':2 );
### END (*GET_STAT*) ;
###
CASE KLASS OF
VARS:
IF VKIND = ACTUAL THEN
BEGIN ACCESS := DRCT; VLEVEL := VLEV;
DPLMT := VADDR
END
ELSE
BEGIN
### IF GET_STAT THEN WRITE(QRR,' #IND',VLEV:3,VADDR:8);
# GEN3(54(*LOD*),ORD('A'),VLEV,VADDR);
ACCESS := INDRCT; IDPLMT := 0
END;
FIELD:
WITH DISPLAY[DISX] DO
IF OCCUR = CREC THEN
BEGIN ACCESS := DRCT; VLEVEL := CLEV;
DPLMT := CDSPL + FLDADDR
END
ELSE
BEGIN
GEN3(54(*LOD*),ORD('A'), LEVEL,VDSPL) ;
### IF GET_STAT THEN WRITE(QRR,' #IND',LEVEL:3,VDSPL:8);
ACCESS := INDRCT; IDPLMT := FLDADDR
END;
FUNC:
IF PFDECKIND = STANDARD THEN ERROR(150)
ELSE
IF PFLEV = 0 THEN ERROR(150) (*EXTERNAL FCT*)
ELSE
IF PFKIND = FORMAL THEN ERROR(151)
ELSE
# IF (FPROCP <> FCP) THEN ERROR(177)
# ELSE
BEGIN ACCESS := DRCT; VLEVEL := PFLEV + 1;
DPLMT := FNCRSLT ; (*RELAT. ADDR. OF FCT. RESULT*)
### (* IF MODIFYING THEN
### WRITE(QRR,' DIR',VLEVEL:3, DPLMT:7) ; *)
END
END (*CASE*) ;
# GATTR.BTYPE := GATTR.TYPTR ;
END (*WITH*);
IF NOT (SY IN SELECTSYS + FSYS) THEN
BEGIN ERROR(59); SKIP(SELECTSYS + FSYS) END;
WHILE SY IN SELECTSYS DO
BEGIN
(*[*) IF SY = LBRACK THEN
BEGIN
###
### IF GET_STAT THEN
### WITH GATTR DO
### BEGIN
### IF ACCESS = DRCT THEN
### WRITE(QRR, ' #DIR',VLEVEL:3,DPLMT:8)
### ELSE IF (ACCESS = INDRCT) AND (IDPLMT <> 0) THEN
### WRITE(QRR,' #DPM ', IDPLMT:8) ;
### WRITE(QRR,' #INX ') ;
### IF MODIFYING THEN
### BEGIN INDEXING := TRUE ; MODIFYING := FALSE END ;
### END ;
###
REPEAT LATTR := GATTR;
WITH LATTR DO
IF TYPTR <> NIL THEN
IF TYPTR↑.FORM <> ARRAYS THEN
BEGIN ERROR(138); TYPTR := NIL END;
LOADADDRESS;
INSYMBOL; EXPRESSION(FSYS + [COMMA,RBRACK]);
LOAD;
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <> SCALAR THEN ERROR(113);
IF LATTR.TYPTR <> NIL THEN
WITH LATTR.TYPTR↑ DO
BEGIN
IF COMPTYPES(INXTYPE,GATTR.TYPTR) THEN
BEGIN
IF INXTYPE <> NIL THEN
BEGIN GETBOUNDS(INXTYPE,LMIN,LMAX);
# IF DEBUG THEN
# GEN3(45(*CHK*),ORD('J'),LMIN,LMAX) ;
# IF LMIN > 0 THEN
# GEN2(22(*DEC*),GETTYPE(GATTR.BTYPE),LMIN)
# ELSE IF LMIN < 0 THEN
GEN2(23(*INC*),GETTYPE(GATTR.BTYPE),-LMIN)
# (*OR SIMPLY GEN1(31,LMIN)*)
END
END
ELSE ERROR(139);
WITH GATTR DO
BEGIN TYPTR := AELTYPE; KIND := VARBL;
ACCESS := INDRCT; IDPLMT := 0 ;
IF GATTR.TYPTR <> NIL THEN
# BEGIN LMIN := TYPTR↑.SIZE ;
# ALIGN(LMIN,TYPTR↑.ALN) ;
# GEN1(36(*IXA*),LMIN)
# END (*TYPTR <> NIL*) ;
END (*WITH GATTR DO*) ;
END
UNTIL SY <> COMMA;
IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12) ;
### IF INDEXING THEN
### BEGIN MODIFYING := TRUE ; INDEXING := FALSE END ;
END (*IF SY = LBRACK*)
ELSE
(*.*) IF SY = PERIOD THEN
BEGIN
WITH GATTR DO
BEGIN
IF TYPTR <> NIL THEN
IF TYPTR↑.FORM <> RECORDS THEN
BEGIN ERROR(140); TYPTR := NIL END;
INSYMBOL;
IF SY = IDENT THEN
BEGIN
IF TYPTR <> NIL THEN
BEGIN SEARCHSECTION(TYPTR↑.FSTFLD,LCP);
IF LCP = NIL THEN
BEGIN ERROR(152); TYPTR := NIL END
ELSE
WITH LCP↑ DO
BEGIN TYPTR := IDTYPE;
CASE ACCESS OF
DRCT: DPLMT := DPLMT + FLDADDR;
INDRCT: IDPLMT := IDPLMT + FLDADDR;
INXD: ERROR(400)
END
END
END;
INSYMBOL
END (*SY = IDENT*)
ELSE ERROR(2)
END (*WITH GATTR*)
END (*IF SY = PERIOD*)
ELSE
(*↑*) BEGIN
IF GATTR.TYPTR <> NIL THEN
WITH GATTR,TYPTR↑ DO
IF FORM = POINTER THEN
# BEGIN
### IF GET_STAT THEN
### IF ACCESS = DRCT THEN
### WRITE(QRR,' #PTR',VLEVEL:3,DPLMT:8)
### ELSE (*ACCESS = INDRCT *)
### WRITE(QRR,' #DPM ',"LEVEL:3,"IDPLMT:8) ;
# LOAD ;
# IF DEBUG THEN CHKBNDS(GATTR.TYPTR) ;
# TYPTR := ELTYPE ;
WITH GATTR DO
BEGIN KIND := VARBL; ACCESS := INDRCT;
IDPLMT := 0
END
END
ELSE
IF FORM = FILES THEN TYPTR := FILTYPE
ELSE ERROR(141);
INSYMBOL
END;
IF NOT (SY IN FSYS + SELECTSYS) THEN
BEGIN ERROR(6); SKIP(FSYS + SELECTSYS) END ;
# GATTR.BTYPE := GATTR.TYPTR ;
END (*WHILE*) ;
###
### IF GET_STAT THEN
### WITH GATTR DO
### BEGIN
### IF ACCESS = DRCT THEN
### WRITE(QRR,' #DIR', VLEVEL:3,DPLMT:8)
### ELSE IF (ACCESS = INDRCT) AND (IDPLMT <> 0) THEN
### WRITE(QRR, ' #DPM ',IDPLMT:8) ;
### IF MODIFYING THEN WRITE(QRR, ' #MND ')
### ELSE WRITE(QRR,' #RND ') ;
### END ;
###
END (*SELECTOR*) ;
(** CALL VARIABLE RWSETUP GETPUTRESETREWRITE READ1 **)
PROCEDURE CALL(FSYS: SETOFSYS; FCP: CTP);
VAR LKEY: 1..NSPROC;
PROCEDURE VARIABLE(FSYS: SETOFSYS);
VAR LCP: CTP;
BEGIN
IF SY = IDENT THEN
BEGIN SEARCHID([VARS,FIELD],LCP); INSYMBOL END
ELSE BEGIN ERROR(2); LCP := UVARPTR END;
SELECTOR(FSYS,LCP)
END (*VARIABLE*) ;
# PROCEDURE RWSETUP(DFILE: ALPHA) ;
# (* TO SET UP FILE ADDRESS PARAMETER FOR READ/WRITE *)
#
# VAR LCP : CTP ; SAVED : BOOLEAN ; TEMPID : ALPHA ; TEMPSY : SYMBOL ;
#
# BEGIN SAVED := TRUE ;
#
# IF SY = IDENT THEN
# BEGIN SEARCHID([VARS,FIELD,FUNC,KONST],LCP) ;
# IF LCP↑.IDTYPE <> NIL THEN
# WITH LCP↑.IDTYPE↑ DO
# IF FORM = FILES THEN
# IF FILTYPE = CHARPTR THEN SAVED := FALSE
# ELSE ERROR(398) ;
# END (* SY = IDENT *) ;
#
# IF SAVED THEN (* USE IMPLIED FILE NAME *)
# BEGIN TEMPSY := SY ; TEMPID := ID ; SY := COMMA ; ID := DFILE ;
# SEARCHID([VARS],LCP) ;
# END (* IF SAVED *)
# ELSE INSYMBOL ;
#
# SELECTOR(FSYS+[COMMA,RPARENT],LCP) ; LOADADDRESS ; (* GET FILE ADR *)
# GEN1(30(*CSP*),31(*SIO*)) ;
# IF SAVED THEN BEGIN ID := TEMPID ; SY := TEMPSY END ;
# END (*RWSETUP*) ;
#
PROCEDURE GETPUTRESETREWRITE;
BEGIN "VARIABLE(FSYS + [RPARENT]); LOADADDRESS;"
## # IF ODD(LKEY) (*GET, RESET*) THEN RWSETUP(NA[39] (*INPUT*))
## # ELSE (*PUT, REWRITE*) RWSETUP(NA[40] (*OUTPUT*) ) ;
# IF EBCDFLG THEN
# IF LKEY > 2 THEN (*RESET , REWRITE*)
# BEGIN GEN2(23(*INC*),ORD('A'),1000) ; EBCDFLG := FALSE END ;
" IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <> FILES THEN ERROR(116);
# GEN1(30(*CSP*),31(*SIO*)) ; "
# GEN1(30(*CSP*),LKEY(*GET,PUT,RES,REW*)) ;
# GEN1(30(*CSP*),30(*EIO*)) ;
END (*GETPUTRESETREWRITE*) ;
PROCEDURE READ1;
" VAR LCP:CTP; LLEV:LEVRANGE; LADDR:ADDRRANGE; "
# BEGIN "LLEV := 1 ; LADDR := FIRSTFILBUF ;"(*ASSUME 'INPUT'*)
## # " IF (SY IN [IDENT,SEMICOLON]) THEN" RWSETUP(NA[39] (*'INPUT '*));
" ELSE BEGIN ERROR(2) ; INSYMBOL END ; "
IF SY = COMMA THEN INSYMBOL ;
## # IF LKEY = 5 (*READ*) THEN IF SY <> IDENT THEN ERROR(2) ;
IF SY = IDENT THEN
### REPEAT MODIFYING := TRUE ;
### VARIABLE(FSYS + [COMMA,RPARENT]) ; MODIFYING := FALSE ;
LOADADDRESS ;
IF GATTR.TYPTR <> NIL THEN
# IF STRING(GATTR.TYPTR) THEN
# BEGIN
# GEN2(51(*LDC*),1,GATTR.TYPTR↑.SIZE DIV CHARSIZE) ;
# GEN1(30(*CSP*),27(*RDS*))
# END
# ELSE
# BEGIN
IF COMPTYPES(INTPTR,GATTR.TYPTR) THEN
GEN1(30(*CSP*),24(*RDI*))
ELSE
IF COMPTYPES(REALPTR,GATTR.TYPTR) THEN
GEN1(30(*CSP*),14(*RDR*))
ELSE
IF COMPTYPES(CHARPTR,GATTR.TYPTR) THEN
GEN1(30(*CSP*),5(*RDC*))
# ELSE
# IF COMPTYPES(BOOLPTR,GATTR.TYPTR) THEN
# GEN1(30(*CSP*),12(*RDB*))
# ELSE ERROR(116) ;
# END ;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST ;
IF LKEY = 11 THEN
BEGIN
GEN1(30(*CSP*),23(*RLN*))
END ;
GEN1(30(*CSP*),30(*EIO*)) ;
END (*READ*) ;
(** WRITE1 PACK1 UNPACK1 **)
PROCEDURE WRITE1;
VAR LSP: STP; DEFAULT, DEFAULT1 : BOOLEAN; LLKEY: 1..NSPROC;
LEN:ADDRRANGE;
# BEGIN LLKEY := LKEY; TEST := FALSE ;
# RWSETUP(NA[40] (*'OUTPUT '*) ) ;
# " IF SY = RPARENT THEN
# BEGIN TEST := TRUE ; IF LLKEY = 6 THEN ERROR(116) ; END ; "
# IF SY = COMMA THEN
# BEGIN INSYMBOL; IF NOT (SY IN CONSTBEGSYS) THEN ERROR(6) END ;
# IF SY IN CONSTBEGSYS THEN
# REPEAT EXPRESSION(FSYS+[COMMA,COLON,RPARENT]) ;
LSP := GATTR.TYPTR;
IF LSP <> NIL THEN
IF LSP↑.FORM <= SUBRANGE THEN LOAD ELSE LOADADDRESS;
DEFAULT := TRUE ; DEFAULT1 := TRUE ;
IF SY = COLON THEN
BEGIN INSYMBOL; EXPRESSION(FSYS + [COMMA,COLON,RPARENT]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> INTPTR THEN ERROR(116);
LOAD; DEFAULT := FALSE ;
IF SY = COLON THEN
BEGIN INSYMBOL; EXPRESSION(FSYS + [COMMA,RPARENT]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> INTPTR THEN ERROR(116);
IF LSP <> REALPTR THEN ERROR(124);
## # LOAD; DEFAULT1 := FALSE ; " ERROR(398); "
END ;
END ;
IF LSP = INTPTR THEN
BEGIN IF DEFAULT THEN GEN2(51(*LDC*),1,12);
GEN1(30(*CSP*),6(*WRI*))
END
ELSE
IF LSP = REALPTR THEN
BEGIN IF DEFAULT THEN GEN2(51(*LDC*),1,14);
IF DEFAULT1 THEN GEN2(51(*LDC*),1,0);
GEN1(30(*CSP*),8(*WRR*))
END
ELSE
IF LSP = CHARPTR THEN
BEGIN IF DEFAULT THEN GEN2(51(*LDC*),1,1);
GEN1(30(*CSP*),9(*WRC*))
END
ELSE
# IF LSP = BOOLPTR THEN
# BEGIN IF DEFAULT THEN GEN2(51(*LDC*),1,5);
# GEN1(30(*CSP*),13(*WRB*))
# END
# ELSE
IF LSP <> NIL THEN
BEGIN
IF LSP↑.FORM = SCALAR THEN ERROR(398)
ELSE
IF STRING(LSP) THEN
BEGIN LEN := LSP↑.SIZE DIV CHARSIZE;
IF DEFAULT THEN
GEN2(51(*LDC*),1,LEN);
GEN2(51(*LDC*),1,LEN);
GEN1(30(*CSP*),10(*WRS*))
END
ELSE ERROR(116)
END;
TEST := SY <> COMMA;
# IF NOT TEST THEN INSYMBOL ;
# UNTIL TEST;
#
IF LLKEY = 12 THEN (*WRITELN*)
BEGIN
GEN1(30(*CSP*),22(*WLN*))
END ;
# GEN1(30(*CSP*),30(*EIO*)) ;
END (*WRITE*) ;
PROCEDURE PACK1;
VAR LSP,LSP1: STP;
BEGIN ERROR(398); VARIABLE(FSYS + [COMMA,RPARENT]);
LSP := NIL; LSP1 := NIL;
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR↑ DO
IF FORM = ARRAYS THEN
BEGIN LSP := INXTYPE; LSP1 := AELTYPE END
ELSE ERROR(116);
IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
EXPRESSION(FSYS + [COMMA,RPARENT]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <> SCALAR THEN ERROR(116)
ELSE
IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN ERROR(116);
IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
VARIABLE(FSYS + [RPARENT]);
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR↑ DO
IF FORM = ARRAYS THEN
BEGIN
IF NOT COMPTYPES(AELTYPE,LSP1)
OR NOT COMPTYPES(INXTYPE,LSP) THEN
ERROR(116)
END
ELSE ERROR(116)
END (*PACK*) ;
PROCEDURE UNPACK1;
VAR LSP,LSP1: STP;
BEGIN ERROR(398); VARIABLE(FSYS + [COMMA,RPARENT]);
LSP := NIL; LSP1 := NIL;
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR↑ DO
IF FORM = ARRAYS THEN
BEGIN LSP := INXTYPE; LSP1 := AELTYPE END
ELSE ERROR(116);
IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
VARIABLE(FSYS + [COMMA,RPARENT]);
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR↑ DO
IF FORM = ARRAYS THEN
BEGIN
IF NOT COMPTYPES(AELTYPE,LSP1)
OR NOT COMPTYPES(INXTYPE,LSP) THEN
ERROR(116)
END
ELSE ERROR(116);
IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
EXPRESSION(FSYS + [RPARENT]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <> SCALAR THEN ERROR(116)
ELSE
IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN ERROR(116);
END (*UNPACK*) ;
(** NEW1 MARK1 RELEASE1 TRAPEXIT **)
PROCEDURE NEW1;
LABEL 1;
VAR LSP,LSP1: STP; VARTS,LMIN,LMAX: INTEGER;
LSIZE,LSZ: ADDRRANGE; LVAL: VALU;
BEGIN VARIABLE(FSYS + [COMMA,RPARENT]); LOADADDRESS;
LSP := NIL; VARTS := 0; LSIZE := 0;
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR↑ DO
IF FORM = POINTER THEN
BEGIN
IF ELTYPE <> NIL THEN
BEGIN LSIZE := ELTYPE↑.SIZE;
IF ELTYPE↑.FORM = RECORDS THEN LSP := ELTYPE↑.RECVAR
END
END
ELSE ERROR(116);
WHILE SY = COMMA DO
BEGIN INSYMBOL;CONSTANT(FSYS + [COMMA,RPARENT],LSP1,LVAL);
VARTS := VARTS + 1;
(*CHECK TO INSERT HERE: IS CONSTANT IN TAGFIELDTYPE RANGE*)
IF LSP = NIL THEN ERROR(158)
ELSE
IF LSP↑.FORM <> TAGFLD THEN ERROR(162)
ELSE
IF LSP↑.TAGFIELDP <> NIL THEN
IF STRING(LSP1) OR (LSP1 = REALPTR) THEN ERROR(159)
ELSE
IF COMPTYPES(LSP↑.TAGFIELDP↑.IDTYPE,LSP1) THEN
BEGIN
LSP1 := LSP↑.FSTVAR;
WHILE LSP1 <> NIL DO
WITH LSP1↑ DO
IF VARVAL.IVAL = LVAL.IVAL THEN
BEGIN LSIZE := SIZE; LSP := SUBVAR;
GOTO 1
END
ELSE LSP1 := NXTVAR;
LSIZE := LSP↑.SIZE; LSP := NIL;
END
ELSE ERROR(116);
1: END (*WHILE*) ;
# ALIGN(LSIZE,MXDATASZE) ;
# GEN1(58(*NEW*),LSIZE);
END (*NEW*) ;
PROCEDURE MARK1;
BEGIN VARIABLE(FSYS+[RPARENT]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM = POINTER THEN
BEGIN LOADADDRESS; GEN0(59(*SAV*)) END
ELSE ERROR(125)
END(*MARK*);
PROCEDURE RELEASE1;
BEGIN VARIABLE(FSYS+[RPARENT]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM = POINTER THEN
BEGIN LOAD; GEN0(60(*RST*)) END
ELSE ERROR(125)
END (*RELEASE*);
# PROCEDURE TRAPEXIT ;
#
# (*THIS PROCEDURE IS TO FACILITATE COMMUNICATION WITH THE OUTSIDE WORLD
# (* AND PROVIDE BREAK POINTS IN THE PASCAL PROGRAM.
# (* 'TRAP(I, R)' RETURNS THE INTEGER CONSTANT I AS WELL AS A POINTER
# (* TO THE SECOND PARAMETER 'R' (I.E. ADDRESS OF R) TO THE OPERATING
# (* SYSTEM. THE FIRST PARAMETER IS INTENDED TO BE USED AS A
# (* 'FUNCTION NUMBER' AND THE SECOND ONE AS THE 'VAR' TYPE ARGUMENT
# (* WHICH MAY BE INSPECTED AND MODIFIED, TO THAT FUNCTION *)
#
# BEGIN " EXPRESSION(FSYS+[RPARENT,COMMA]) ; "
# IF GATTR.TYPTR <> INTPTR THEN ERROR(116) ;
# IF LKEY = 14 THEN (*TRAP*)
# BEGIN
# IF SY <> COMMA THEN ERROR(6)
# ELSE
# BEGIN INSYMBOL ;
# EXPRESSION(FSYS+[RPARENT]) ;
# WITH GATTR DO
# IF TYPTR <> NIL THEN
# BEGIN
# IF KIND <> VARBL THEN
# IF TYPTR↑.FORM <= POWER THEN
# BEGIN LOAD ;
# KIND := VARBL ; ACCESS := DRCT ; VLEVEL := LEVEL ;
# ALIGN(LC,MXDATASZE) ; DPLMT := LC ; BTYPE := TYPTR ;
# STORE(GATTR) ;
# END ;
# LOADADDRESS ;
# END ;
# END (*WITH*) ;
# END ;
# GEN1(30(*CSP*),LKEY+14 (*TRP*) (*XIT*)) ;
# END (* TRAPEXIT *) ;
(** ABS1 SQR1 TRUNC1 ODD1 ORD1 CHR1 PREDSUCCTIM EOFEOLN MATH **)
PROCEDURE ABS1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR = INTPTR THEN GEN0(0(*ABI*))
ELSE
IF GATTR.TYPTR = REALPTR THEN GEN0(1(*ABR*))
ELSE BEGIN ERROR(125); GATTR.TYPTR := INTPTR END
END (*ABS*) ;
PROCEDURE SQR1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR = INTPTR THEN GEN0(24(*SQI*))
ELSE
IF GATTR.TYPTR = REALPTR THEN GEN0(25(*SQR*))
ELSE BEGIN ERROR(125); GATTR.TYPTR := INTPTR END
END (*SQR*) ;
PROCEDURE TRUNC1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> REALPTR THEN ERROR(125);
GEN0(27(*TRC*));
GATTR.TYPTR := INTPTR
END (*TRUNC*) ;
PROCEDURE ODD1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> INTPTR THEN ERROR(125);
GEN0(20(*ODD*));
GATTR.TYPTR := BOOLPTR
END (*ODD*) ;
PROCEDURE ORD1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM >= POWER THEN ERROR(125);
# GEN0(61(*ORD*)) ;
GATTR.TYPTR := INTPTR
END (*ORD1*) ;
PROCEDURE CHR1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> INTPTR THEN ERROR(125);
# GEN0(62(*CHR*)) ;
GATTR.TYPTR := CHARPTR
END (*CHR*) ;
PROCEDURE PREDSUCCTIM;
# BEGIN (*ERROR(398);*) (*TRANSLATES INTO 'DEC' AND 'INC'*)
# IF GATTR.TYPTR <> NIL THEN
# IF LKEY = 24 THEN
# BEGIN IF GATTR.TYPTR <> INTPTR THEN ERROR(116) ;
# GEN1(30(*CSP*),21(*CLK*)) ;
# END
# ELSE
# IF (GATTR.TYPTR = REALPTR) OR (GATTR.TYPTR↑.FORM <> SCALAR) THEN
# ERROR(125)
# ELSE GEN2(LKEY(*DEC,INC*),GETTYPE(GATTR.BTYPE),1) ;
(* LKEY HAPPENS TO BE THE OPCODE AS WELL *)
# END (*PREDSUCCTIM*) ;
PROCEDURE EOFEOLN;
BEGIN
## # RWSETUP(NA[39] (*'INPUT '*) ) ;
# " GEN1(30(*CSP*),31(*SIO*)) ;
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <> FILES THEN ERROR(125); "
# " IF LKEY = 10 THEN GEN1(30(*CSP*),25(*EOF*))
ELSE GEN1(30(*CSP*),26(*ELN*)); "
(* LKEY HAPPENS TO BE THE CSP NUMBER AS WELL ! *)
## # GEN1(30(*CSP*), LKEY(*EOF*)(*ELN*)) ;
# GEN1(30(*CSP*),30(*EIO*)) ;
GATTR.TYPTR := BOOLPTR
END (*EOF*) ;
PROCEDURE MATH;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR = INTPTR THEN
BEGIN GEN0(10(*FLT*)) ;
GATTR.TYPTR := REALPTR ;
END ;
IF GATTR.TYPTR <> REALPTR THEN ERROR(116)
ELSE GEN1(30(*CSP*), LKEY-12(*SIN..ATAN*)) ;
END (*MATH*) ;
(** CALLNONSTANDARD **)
PROCEDURE CALLNONSTANDARD;
VAR NXT,LCP: CTP; LSP: STP; LKIND: IDKIND; LB: BOOLEAN;
LOCPAR, LLC: ADDRRANGE;
BEGIN LOCPAR := 0;
WITH FCP↑ DO
BEGIN NXT := NEXT; LKIND := PFKIND;
# " IF NOT EXTRN THEN
# BEGIN "
"S0" " GEN1(41(*MST*),PFLEV) ; "
"S1" GEN3(41(*MST*), PFLEV+1, FPRMSZE, RPRMSZE) ;
###
### T_CLIST := CALL_HEAD ;
### WHILE NAME > T_CLIST↑.NAME DO T_CLIST := T_CLIST↑.NXT; (*X10S1*)
### (*EJG*)(* WHILE NAME < T_CLIST↑.NAME DO T_CLIST := T_CLIST↑.NXT;*)(*X10S1*)
(* EJG 11/25/78 Above comparison crock is because all spaces are larger than
identifier names in 370 PASCAL and PDP-10 PASCAL (because ID's are
negative on PDP-10!), but smaller on S-1 PASCAL. Sigh. This should
be fixed better someday...*)
### IF T_CLIST↑.NAME <> NAME THEN
### BEGIN NEW(T2_CLIST) ; T2_CLIST↑ := T_CLIST↑ ;
### T_CLIST↑.NAME := NAME ; T_CLIST↑.NXT := T2_CLIST ;
### T_CLIST↑.CNT := 1 ; T_CLIST↑.LVL := PFLEV ;
### IF PFLEV = LEVEL THEN LOCAL_CALL := TRUE ;
### END
### ELSE T_CLIST↑.CNT := T_CLIST↑.CNT+1 ;
###
# " END (* IF NOT EXTRN *) ; "
END;
IF SY = LPARENT THEN
BEGIN LLC := LC;
REPEAT LB := FALSE; (*DECIDE WHETHER PROC/FUNC MUST BE PASSED*)
IF LKIND = ACTUAL THEN
BEGIN
IF NXT = NIL THEN ERROR(126)
ELSE LB := NXT↑.KLASS IN [PROC,FUNC]
END ELSE ERROR(398);
(*FOR FORMAL PROC/FUNC LB IS FALSE AND EXPRESSION
WILL BE CALLED, WHICH WILL ALLWAYS INTERPRET A PROC/FUNC ID
AT ITS BEGINNING AS A CALL RATHER THAN A PARAMETER PASSING.
IN THIS IMPLEMENTATION, PARAMETER PROCEDURES/FUNCTIONS
ARE THEREFORE NOT ALLOWED TO HAVE PROCEDURE/FUNCTION
PARAMETERS*)
INSYMBOL;
IF LB THEN (*PASS FUNCTION OR PROCEDURE*)
BEGIN ERROR(398);
IF SY <> IDENT THEN
BEGIN ERROR(2); SKIP(FSYS + [COMMA,RPARENT]) END
ELSE
BEGIN
IF NXT↑.KLASS = PROC THEN SEARCHID([PROC],LCP)
ELSE
BEGIN SEARCHID([FUNC],LCP);
IF NOT COMPTYPES(LCP↑.IDTYPE,NXT↑.IDTYPE) THEN
ERROR(128)
END;
INSYMBOL;
IF NOT (SY IN FSYS + [COMMA,RPARENT]) THEN
BEGIN ERROR(6); SKIP(FSYS + [COMMA,RPARENT]) END
END
END (*IF LB*)
ELSE
BEGIN
### IF NXT <> NIL THEN
### IF NXT↑.VKIND = FORMAL THEN MODIFYING := TRUE ;
EXPRESSION(FSYS + [COMMA,RPARENT]);
### MODIFYING := FALSE ;
IF GATTR.TYPTR <> NIL THEN
IF LKIND = ACTUAL THEN
BEGIN
IF NXT <> NIL THEN
BEGIN LSP := NXT↑.IDTYPE;
IF LSP <> NIL THEN
BEGIN
IF (NXT↑.VKIND = ACTUAL) THEN
# IF LSP↑.FORM <= POWER THEN
# BEGIN LOAD;
# IF DEBUG THEN
# BEGIN ASSIGN := TRUE ;
# CHKBNDS(LSP) ; ASSIGN := FALSE ;
# END ;
IF COMPTYPES(REALPTR,LSP)
AND (GATTR.TYPTR = INTPTR) THEN
BEGIN GEN0(10(*FLT*));
GATTR.TYPTR := REALPTR
END;
LOCPAR := LOCPAR+ 1 (*LSP↑.SIZE*) ;
# IF PACKDATA THEN
# BEGIN
# IF LSP↑.SIZE = 4 THEN GEN0(61(*ORD*));
# IF LSP↑.SIZE = 1 THEN GEN0(62(*CHR*));
END (*PACKDATA*) ;
"S1" IF NOT FCP↑.EXTRN THEN
"S1" GEN1(64(*PRM*), GETTYPE(LSP));
END
ELSE
BEGIN
LOADADDRESS;
LOCPAR := LOCPAR+ 1 (*PTRSIZE*);
"S1" IF NOT FCP↑.EXTRN THEN
"S1" GEN1(64(*PRM*), ORD('A')) ;
END
ELSE (* VKIND = FORMAL I.E. VAR PARM *)
IF GATTR.KIND = VARBL THEN
BEGIN LOADADDRESS;
LOCPAR := LOCPAR + 1 (*PTRSIZE*);
"S1" IF NOT FCP↑.EXTRN THEN
"S1" GEN1(64(*PRM*), ORD('A')) ;
IF GATTR.BTYPE↑.SIZE <> LSP↑.SIZE THEN
ERROR(142) ;
END
ELSE ERROR(154);
IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN
ERROR(142)
END
END
END
ELSE (*LKIND = FORMAL*)
BEGIN (*PASS FORMAL PROC/FUNC PARAM*)
END
END;
IF (LKIND = ACTUAL) AND (NXT <> NIL) THEN NXT := NXT↑.NEXT
UNTIL SY <> COMMA;
LC := LLC;
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END (*IF LPARENT*);
# LOCPAR := LOCPAR*2 ;
IF LKIND = ACTUAL THEN
BEGIN IF NXT <> NIL THEN ERROR(126);
WITH FCP↑ DO
" IF EXTRN THEN GEN1(30(*CSP*),PFNAME)
# ELSE "
# BEGIN
# IF SAVEFP THEN LOCPAR := LOCPAR+1 ; (*ENCODE SAVE FPR FLG*)
GENCUPENT(46(*CUP*),PROCTYPE(FCP),LOCPAR,PFNAME,NAME);
END ;
END;
# GATTR.TYPTR := FCP↑.IDTYPE ; GATTR.BTYPE := GATTR.TYPTR ;
END (*CALLNONSTANDARD*) ;
BEGIN (*CALL*)
IF FCP↑.PFDECKIND = STANDARD THEN
BEGIN "IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);"
LKEY := FCP↑.KEY;
## # IF SY = LPARENT THEN
## # BEGIN INSYMBOL ;
## # IF SY = RPARENT THEN
## # IF NOT (LKEY IN [1,2,3,4,11,12,25,26]) THEN ERROR(7) ;
(*GET,PUT,RESET,REWRITE,RDLN,WRITELN,EOF,ELN*)
## # END
## # ELSE
## # BEGIN IF NOT (LKEY IN [1,2,3,4,11,12,25,26]) THEN ERROR(6) ;
(*GET,PUT,RESET,REWRITE,RDLN,WRITELN,EOF,ELN*)
## # IF SY =RPARENT THEN ERROR(6) ;
## # END ;
" IF FCP↑.KLASS = PROC THEN "
## #
## # IF LKEY IN [14..24, 27..32 (*TRAP,EXIT,ABS..MATH*)] THEN
## # BEGIN
IF LKEY = 14 (*TRAP*) THEN EXPRESSION(FSYS+[COMMA])
ELSE EXPRESSION(FSYS+[RPARENT]) ;
LOAD ;
END ;
## #
CASE LKEY OF
1,2,
3,4: GETPUTRESETREWRITE;
5,11: READ1;
6,12: WRITE1;
7: PACK1;
8: UNPACK1;
9: NEW1;
10: RELEASE1;
13: MARK1;
14,15: TRAPEXIT ;
" END
ELSE
BEGIN EXPRESSION(FSYS + [RPARENT]);
IF LKEY <= 9 THEN LOAD ELSE LOADADDRESS;
CASE LKEY OF "
16: ABS1;
17: SQR1;
18: TRUNC1;
19: ODD1;
20: ORD1;
21: CHR1;
22,23,24 :PREDSUCCTIM;
25,26 :EOFEOLN ;
## # 27,28,29,
## # 30,31,32 :MATH ;
END (*CASE LKEY OF*) ;
# IF LKEY IN [16..24, 27..32] THEN GATTR.BTYPE := GATTR.TYPTR ;
## # IF SY = RPARENT THEN INSYMBOL
## # ELSE IF NOT (LKEY IN [1,2,3,4,11,12,25,26]) THEN ERROR(4) ;
END (*STANDARD PROCEDURES AND FUNCTIONS*)
ELSE CALLNONSTANDARD
END (*CALL*) ;
(** EXPRESSION SIMPLEEXPRESSION TERM FACTOR **)
PROCEDURE EXPRESSION;
VAR LATTR: ATTR; LOP: OPERATOR; TYPIND: CHAR; LSIZE: ADDRRANGE;
PROCEDURE SIMPLEEXPRESSION(FSYS: SETOFSYS);
VAR LATTR: ATTR; LOP: OPERATOR; SIGNED: BOOLEAN;
PROCEDURE TERM(FSYS: SETOFSYS);
VAR LATTR: ATTR; LOP: OPERATOR;
PROCEDURE FACTOR(FSYS: SETOFSYS);
VAR LCP: CTP; LVP: CSP; VARPART: BOOLEAN;
(*SETCH*) CSTPART: SETREP; LSP: STP; I: SET_EL_TYP;
BEGIN
IF NOT (SY IN FACBEGSYS) THEN
BEGIN ERROR(58); SKIP(FSYS + FACBEGSYS);
GATTR.TYPTR := NIL
END;
WHILE SY IN FACBEGSYS DO
BEGIN
CASE SY OF
(*ID*) IDENT:
BEGIN SEARCHID([KONST,VARS,FIELD,FUNC],LCP);
INSYMBOL;
IF LCP↑.KLASS = FUNC THEN
# BEGIN CALL(FSYS,LCP);
# WITH GATTR DO
# BEGIN KIND := EXPR;
# IF TYPTR <> NIL THEN
# IF TYPTR↑.FORM=SUBRANGE THEN
# TYPTR := TYPTR↑.RANGETYPE
# END
# END
ELSE
IF LCP↑.KLASS = KONST THEN
WITH GATTR, LCP↑ DO
BEGIN TYPTR := IDTYPE; KIND := CST;
# CVAL := VALUES; GATTR.BTYPE := GATTR.TYPTR
END
ELSE
BEGIN SELECTOR(FSYS,LCP);
IF GATTR.TYPTR<>NIL THEN(*ELIM.SUBR.TYPES TO*)
WITH GATTR,TYPTR↑ DO(*SIMPLIFY LATER TESTS*)
IF FORM = SUBRANGE THEN
TYPTR := RANGETYPE
END
END;
(*CST*) INTCONST:
BEGIN
WITH GATTR DO
BEGIN TYPTR := INTPTR; KIND := CST;
# CVAL := VAL; BTYPE := TYPTR
END;
INSYMBOL
END;
REALCONST:
BEGIN
WITH GATTR DO
BEGIN TYPTR := REALPTR; KIND := CST;
CVAL := VAL
END;
INSYMBOL
END;
STRINGCONST:
BEGIN
WITH GATTR DO
BEGIN
IF LNGTH = 1 THEN TYPTR := CHARPTR
ELSE
BEGIN NEW(LSP,ARRAYS);
WITH LSP↑ DO
BEGIN AELTYPE := CHARPTR; FORM:=ARRAYS;
INXTYPE := NIL; SIZE := LNGTH*CHARSIZE
END;
TYPTR := LSP
END;
KIND := CST; CVAL := VAL
END;
INSYMBOL
END;
(*(*) LPARENT:
BEGIN INSYMBOL; EXPRESSION(FSYS + [RPARENT]);
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END;
(*NOT*) NOTSY:
BEGIN INSYMBOL; FACTOR(FSYS);
LOAD; GEN0(19(*NOT*));
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> BOOLPTR THEN
BEGIN ERROR(135); GATTR.TYPTR := NIL END;
END;
(*[*) LBRACK:
BEGIN INSYMBOL;
(*SETCH*) CSTPART := NULL_SET;
VARPART := FALSE;
NEW(LSP,POWER);
WITH LSP↑ DO
BEGIN ELSET:=NIL;SIZE:=SETSIZE;FORM:=POWER END;
IF SY = RBRACK THEN
BEGIN
WITH GATTR DO
BEGIN TYPTR := LSP; KIND := CST END;
INSYMBOL
END
ELSE
BEGIN
# REPEAT EXPRESSION(FSYS + [COMMA,DOTDOT,RBRACK]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <> SCALAR THEN
BEGIN ERROR(136); GATTR.TYPTR := NIL END
ELSE
IF COMPTYPES(LSP↑.ELSET,GATTR.TYPTR) THEN
BEGIN
IF GATTR.KIND = CST THEN
# BEGIN
# IF (GATTR.CVAL.IVAL < 0) THEN
# ERROR(304)
# ELSE
#(*SETCH*) BUILD_SET(GATTR.CVAL.IVAL,CSTPART);
# IF SY = DOTDOT THEN (*RANGE GIVEN*)
# BEGIN INSYMBOL ; LATTR := GATTR ;
# EXPRESSION(FSYS+[COMMA,RBRACK]) ;
# IF GATTR.TYPTR <> LATTR.TYPTR THEN
# ERROR(137)
# ELSE
# FOR I := LATTR.CVAL.IVAL TO
# GATTR.CVAL.IVAL DO
#(*SETCH*) BUILD_SET(I,CSTPART);
# END (* IF SY = COLON *) ;
# IF GATTR.CVAL.IVAL > MAXSETEL THEN
# ERROR(304) ;
# END (* GATTR.KIND = CST *)
# ELSE
# BEGIN LOAD;
# IF NOT COMPTYPES(GATTR.TYPTR,INTPTR)
# THEN GEN0(61(*ORD*));
# IF DEBUG THEN
# GEN3(45(*CHK*),ORD('S'),0,MAXSETEL);
# GEN0(29(*SGS*));
IF VARPART THEN GEN0(28(*UNI*))
ELSE VARPART := TRUE
END;
LSP↑.ELSET := GATTR.TYPTR;
GATTR.TYPTR := LSP
END
ELSE ERROR(137);
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12)
END;
IF VARPART THEN
BEGIN
(*SETCH*) IF CSTPART <> NULL_SET THEN
BEGIN NEW(LVP,PSET); LVP↑.PVAL := CSTPART;
"LVP↑.CCLASS := PSET;"
# CSTPTR := LVP;
# GEN2(51(*LDC*),5,0);
GEN0(28(*UNI*)); GATTR.KIND := EXPR
END
END
ELSE
BEGIN NEW(LVP,PSET); LVP↑.PVAL := CSTPART;
"LVP↑.CCLASS := PSET;"
GATTR.CVAL.VALP := LVP
END
END
END (*CASE*) ;
IF NOT (SY IN FSYS) THEN
BEGIN ERROR(6); SKIP(FSYS + FACBEGSYS) END
END (*WHILE*)
END (*FACTOR*) ;
BEGIN (*TERM*)
FACTOR(FSYS + [MULOP]);
WHILE SY = MULOP DO
BEGIN LOAD; LATTR := GATTR; LOP := OP;
INSYMBOL; FACTOR(FSYS + [MULOP]); LOAD;
IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
CASE LOP OF
(***) MUL: IF (LATTR.TYPTR=INTPTR)AND(GATTR.TYPTR=INTPTR)
THEN GEN0(15(*MPI*))
ELSE
BEGIN
# IF GATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(10(*FLT*));
# GATTR.TYPTR := REALPTR
# END
# ELSE
# IF LATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(9(*FLO*));
# LATTR.TYPTR := REALPTR
END;
IF (LATTR.TYPTR = REALPTR)
AND(GATTR.TYPTR=REALPTR)THEN GEN0(16(*MPR*))
ELSE
IF(LATTR.TYPTR↑.FORM=POWER)
AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR)THEN
GEN0(12(*INT*))
ELSE BEGIN ERROR(134);GATTR.TYPTR:=NIL END
END;
(*/*) RDIV: BEGIN
# IF GATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(10(*FLT*));
# GATTR.TYPTR := REALPTR
# END;
# IF LATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(9(*FLO*));
# LATTR.TYPTR := REALPTR
# END;
IF (LATTR.TYPTR = REALPTR)
AND (GATTR.TYPTR=REALPTR)THEN GEN0(7(*DVR*))
ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
END;
(*DIV*) IDIV: IF (LATTR.TYPTR = INTPTR)
AND (GATTR.TYPTR = INTPTR) THEN GEN0(6(*DVI*))
ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END;
(*MOD*) IMOD: IF (LATTR.TYPTR = INTPTR)
# AND (GATTR.TYPTR = INTPTR) THEN GEN0(14 )
ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END;
(*AND*) ANDOP:IF (LATTR.TYPTR = BOOLPTR)
AND (GATTR.TYPTR = BOOLPTR) THEN GEN0(4(*AND*))
ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
END (*CASE*)
ELSE GATTR.TYPTR := NIL
END (*WHILE*)
END (*TERM*) ;
BEGIN (*SIMPLEEXPRESSION*)
SIGNED := FALSE;
IF (SY = ADDOP) AND (OP IN [PLUS,MINUS]) THEN
BEGIN SIGNED := OP = MINUS; INSYMBOL END;
TERM(FSYS + [ADDOP]);
IF SIGNED THEN
BEGIN LOAD;
IF GATTR.TYPTR = INTPTR THEN GEN0(17(*NGI*))
ELSE
IF GATTR.TYPTR = REALPTR THEN GEN0(18(*NGR*))
ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
END;
WHILE SY = ADDOP DO
BEGIN LOAD; LATTR := GATTR; LOP := OP;
INSYMBOL; TERM(FSYS + [ADDOP]); LOAD;
IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
CASE LOP OF
(*+*) PLUS:
IF (LATTR.TYPTR = INTPTR)AND(GATTR.TYPTR = INTPTR) THEN
GEN0(2(*ADI*))
ELSE
BEGIN
# IF GATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(10(*FLT*));
# GATTR.TYPTR := REALPTR
# END
# ELSE
# IF LATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(9(*FLO*));
# LATTR.TYPTR := REALPTR
# END;
IF (LATTR.TYPTR = REALPTR)AND(GATTR.TYPTR = REALPTR)
THEN GEN0(3(*ADR*))
ELSE IF(LATTR.TYPTR↑.FORM=POWER)
AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
GEN0(28(*UNI*))
ELSE BEGIN ERROR(134);GATTR.TYPTR:=NIL END
END;
(*-*) MINUS:
IF (LATTR.TYPTR = INTPTR)AND(GATTR.TYPTR = INTPTR) THEN
GEN0(21(*SBI*))
ELSE
BEGIN
# IF GATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(10(*FLT*));
# GATTR.TYPTR := REALPTR
# END
# ELSE
# IF LATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(9(*FLO*));
# LATTR.TYPTR := REALPTR
END;
IF (LATTR.TYPTR = REALPTR)AND(GATTR.TYPTR = REALPTR)
THEN GEN0(8(*SBR*))
ELSE
IF (LATTR.TYPTR↑.FORM = POWER)
AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
GEN0(5(*DIF*))
ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
END;
(*OR*) OROP:
IF(LATTR.TYPTR=BOOLPTR)AND(GATTR.TYPTR=BOOLPTR)THEN
GEN0(13(*IOR*))
ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
END (*CASE*)
ELSE GATTR.TYPTR := NIL
END (*WHILE*)
END (*SIMPLEEXPRESSION*) ;
(** ASSIGNMENT **)
BEGIN (*EXPRESSION*)
SIMPLEEXPRESSION(FSYS + [RELOP]);
IF SY = RELOP THEN
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <= POWER THEN LOAD
ELSE LOADADDRESS;
LATTR := GATTR; LOP := OP;
# (*IN*) IF LOP = INOP THEN
# BEGIN
# IF NOT COMPTYPES(GATTR.TYPTR,INTPTR) THEN GEN0(61(*ORD*)) ;
# IF DEBUG THEN GEN3(45(*CHK*),ORD('S'),0,MAXSETEL) ;
# END ;
INSYMBOL; SIMPLEEXPRESSION(FSYS);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <= POWER THEN LOAD
ELSE LOADADDRESS;
IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
IF LOP = INOP THEN
IF GATTR.TYPTR↑.FORM = POWER THEN
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR↑.ELSET) THEN
GEN0(11(*INN*))
ELSE BEGIN ERROR(129); GATTR.TYPTR := NIL END
ELSE BEGIN ERROR(130); GATTR.TYPTR := NIL END
ELSE
BEGIN
IF LATTR.TYPTR <> GATTR.TYPTR THEN
# IF GATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(10(*FLT*));
# GATTR.TYPTR := REALPTR
# END
# ELSE
# IF LATTR.TYPTR = INTPTR THEN
# BEGIN GEN0(9(*FLO*));
# LATTR.TYPTR := REALPTR
END;
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
BEGIN LSIZE := LATTR.TYPTR↑.SIZE;
CASE LATTR.TYPTR↑.FORM OF
SCALAR:
IF LATTR.TYPTR = REALPTR THEN TYPIND := 'R'
ELSE
IF LATTR.TYPTR = BOOLPTR THEN TYPIND := 'B'
# ELSE
# IF LATTR.TYPTR = CHARPTR THEN TYPIND := 'C'
# ELSE TYPIND := 'I' ;
POINTER:
BEGIN
IF LOP IN [LTOP,LEOP,GTOP,GEOP] THEN ERROR(131);
TYPIND := 'A'
END;
POWER:
BEGIN IF LOP IN [LTOP,GTOP] THEN ERROR(132);
TYPIND := 'S'
END;
ARRAYS:
BEGIN
IF NOT STRING(LATTR.TYPTR)
AND(LOP IN[LTOP,LEOP,GTOP,GEOP])THEN ERROR(131);
TYPIND := 'M'
END;
RECORDS:
BEGIN
IF LOP IN [LTOP,LEOP,GTOP,GEOP] THEN ERROR(131);
TYPIND := 'M'
END;
FILES:
BEGIN ERROR(133); TYPIND := 'F' END
END;
CASE LOP OF
LTOP: GEN2(53(*LES*),ORD(TYPIND),LSIZE);
LEOP: GEN2(52(*LEQ*),ORD(TYPIND),LSIZE);
GTOP: GEN2(49(*GRT*),ORD(TYPIND),LSIZE);
GEOP: GEN2(48(*GEQ*),ORD(TYPIND),LSIZE);
NEOP: GEN2(55(*NEQ*),ORD(TYPIND),LSIZE);
EQOP: GEN2(47(*EQU*),ORD(TYPIND),LSIZE)
END
END
ELSE ERROR(129)
END;
GATTR.TYPTR := BOOLPTR; GATTR.KIND := EXPR
END (*SY = RELOP*)
END (*EXPRESSION*) ;
PROCEDURE ASSIGNMENT(FCP: CTP);
VAR LATTR: ATTR;
BEGIN
### MODIFYING := TRUE ;
SELECTOR(FSYS + [BECOMES],FCP);
### MODIFYING := FALSE ; VAR_MOD := VAR_MOD+1 ;
IF SY = BECOMES THEN
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF (GATTR.ACCESS<>DRCT) OR (GATTR.TYPTR↑.FORM>POWER) THEN
LOADADDRESS;
LATTR := GATTR;
INSYMBOL; EXPRESSION(FSYS);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <= POWER THEN LOAD
ELSE LOADADDRESS;
IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
BEGIN
IF COMPTYPES(REALPTR,LATTR.TYPTR)AND(GATTR.TYPTR=INTPTR)THEN
BEGIN GEN0(10(*FLT*));
GATTR.TYPTR := REALPTR
END;
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
BEGIN
# IF DEBUG THEN
# BEGIN
# ASSIGN := TRUE ; CHKBNDS(LATTR.TYPTR); ASSIGN := FALSE
# END ;
CASE LATTR.TYPTR↑.FORM OF
SCALAR,
SUBRANGE,
POINTER,
POWER: STORE(LATTR);
ARRAYS,
RECORDS: GEN1(40(*MOV*),LATTR.TYPTR↑.SIZE);
FILES: ERROR(146)
END (*CASE LATTR...*)
# END
ELSE ERROR(129)
END
END (*SY = BECOMES*)
ELSE ERROR(51)
END (*ASSIGNMENT*) ;
(** GOTOSTATEMENT COMPOUNDSTATEMENT IFSTATEMENT **)
PROCEDURE GOTOSTATEMENT;
VAR LLP: LBP; FOUND: BOOLEAN; TTOP,TTOP1: DISPRANGE;
BEGIN
IF SY = INTCONST THEN
BEGIN
FOUND := FALSE; TTOP := TOP;
# WHILE DISPLAY[TTOP].OCCUR <> BLCK DO TTOP := TTOP - 1;
# TTOP1 := TTOP;
# REPEAT
LLP := DISPLAY[TTOP].FLABEL;
WHILE (LLP <> NIL) AND NOT FOUND DO
WITH LLP↑ DO
IF LABVAL = VAL.IVAL THEN
BEGIN FOUND := TRUE;
IF TTOP = TTOP1 THEN
BEGIN
GENUJPFJP(57(*UJP*),LABNAME) ;
"CTR" CTREMIT(CTRGOTO, 0, LINECOUNT, 0, LINECOUNT)
END
ELSE (*GOTO LEADS OUT OF PROCEDURE*) ERROR(398)
END
ELSE LLP := NEXTLAB;
TTOP := TTOP - 1
UNTIL FOUND OR (TTOP = 0);
IF NOT FOUND THEN ERROR(167);
INSYMBOL
END
ELSE ERROR(15)
END (*GOTOSTATEMENT*) ;
PROCEDURE COMPOUNDSTATEMENT;
BEGIN
REPEAT
REPEAT STATEMENT(FSYS + [SEMICOLON,ENDSY])
UNTIL NOT (SY IN STATBEGSYS);
TEST := SY <> SEMICOLON;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = ENDSY THEN INSYMBOL ELSE ERROR(13)
END (*COMPOUNDSTATEMENET*) ;
PROCEDURE IFSTATEMENT;
VAR LCIX1,LCIX2: INTEGER;
"CTR" FIRSTLN, MIDLN : INTEGER; CTRNO : CTRRANGE;
BEGIN EXPRESSION(FSYS + [THENSY]);
GENLABEL(LCIX1); GENFJP(LCIX1);
IF SY = THENSY THEN INSYMBOL ELSE ERROR(52);
"CTR" FIRSTLN := LINECOUNT; CTRNO := CTRGEN;
"CTR" (*** COUNTER HERE ***)
STATEMENT(FSYS + [ELSESY]);
IF SY = ELSESY THEN
BEGIN GENLABEL(LCIX2); GENUJPFJP(57(*UJP*),LCIX2);
PUTLABEL(LCIX1);
INSYMBOL;
"CTR" MIDLN := LINECOUNT ;
STATEMENT(FSYS);
PUTLABEL(LCIX2)
END
ELSE
BEGIN
PUTLABEL(LCIX1) ;
"CTR" MIDLN := 0;
END ;
"CTR" CTREMIT(CTRIF, CTRNO, FIRSTLN, MIDLN, LINECOUNT)
END (*IFSTATEMENT*) ;
(** CASESTATEMENT REPEATSTATEMENT WHILESTATEMENT **)
PROCEDURE CASESTATEMENT;
LABEL 1;
TYPE CIP = ↑CASEINFO;
CASEINFO = PACKED
RECORD NEXT: CIP;
CSSTART: INTEGER;
CSLAB: INTEGER
END;
# # VAR LSP,LSP1: STP; FSTPTR,LPT1,LPT2,LPT3: CIP; LVAL,LVAL1: VALU;
# LADDR, LCIX, LCIX1, UBND, LBND: ADDRRANGE ;
# LMIN, LMAX : INTEGER ;
"CTR" FIRSTLN : INTEGER; TEMPLN : INTEGER;
"CTR" CTRCASES : INTEGER; CTRNO : CTRRANGE;
BEGIN EXPRESSION(FSYS + [OFSY,COMMA,COLON]);
# LOAD ; " ALIGN(LC,INTSIZE) ; LLC := LC ; "
# LSP := GATTR.TYPTR;
# IF LSP <> NIL THEN
# IF (LSP↑.FORM <> SCALAR) OR (LSP = REALPTR) THEN
# BEGIN ERROR(144); LSP := NIL END
# ELSE IF NOT COMPTYPES(LSP,INTPTR) THEN GEN0(61(*ORD*)) ;
# IF DEBUG THEN CHKBNDS(GATTR.TYPTR) ;
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8);
# FSTPTR := NIL ; GENLABEL(LBND) ; GENLABEL(UBND) ;
# GENLABEL(LCIX) ; GENLABEL(LADDR);
# (* WE SHOULD HAVE: LADDR = LCIX+1 = UBND+2 = LBND+3 HERE *)
# GENUJPFJP(44 (*XJP*), LBND) ; "GENCASE(LBND,UBND,LCIX) ; "
"CTR" FIRSTLN := LINECOUNT; CTRCASES := 0;
REPEAT
LPT3 := NIL; GENLABEL(LCIX1);
# IF NOT(SY IN [SEMICOLON,ENDSY]) THEN
# BEGIN
REPEAT CONSTANT(FSYS + [COMMA,COLON,DOTDOT],LSP1,LVAL);
IF LSP <> NIL THEN
IF COMPTYPES(LSP,LSP1) THEN
# # BEGIN LVAL1.IVAL := LVAL.IVAL ;
# # IF SY = DOTDOT THEN
# # BEGIN INSYMBOL ;
# # CONSTANT(FSYS+[COMMA,COLON],LSP1,LVAL1)
# # END ;
# # IF COMPTYPES(LSP,LSP1) THEN
# # FOR LMIN := LVAL.IVAL TO LVAL1.IVAL DO
BEGIN LPT1 := FSTPTR; LPT2 := NIL;
WHILE LPT1 <> NIL DO
WITH LPT1↑ DO
BEGIN
IF CSLAB <= LMIN THEN
BEGIN
IF CSLAB = LMIN THEN ERROR(156);
GOTO 1
END;
LPT2 := LPT1; LPT1 := NEXT
END;
1: NEW(LPT3);
WITH LPT3↑ DO
BEGIN NEXT := LPT1; CSLAB := LMIN ;
CSSTART := LCIX1
END;
IF LPT2 = NIL THEN FSTPTR := LPT3
ELSE LPT2↑.NEXT := LPT3
END
ELSE ERROR(147);
END ;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
PUTLABEL(LCIX1);
"CTR" TEMPLN := LINECOUNT; (*** COUNTER HERE ***)
"CTR" CTRNO := CTRGEN; CTRCASES := CTRCASES+1 ;
REPEAT STATEMENT(FSYS + [SEMICOLON])
UNTIL NOT (SY IN STATBEGSYS);
IF LPT3 <> NIL THEN
GENUJPFJP(57(*UJP*),LADDR);
"CTR" CTREMIT(CTRCASE, CTRNO, TEMPLN, 0, LINECOUNT);
# END ;
TEST := SY <> SEMICOLON;
IF NOT TEST THEN INSYMBOL ;
UNTIL TEST;
IF FSTPTR <> NIL THEN
BEGIN LMAX := FSTPTR↑.CSLAB;
(*REVERSE POINTERS*)
LPT1 := FSTPTR; FSTPTR := NIL;
REPEAT LPT2 := LPT1↑.NEXT; LPT1↑.NEXT := FSTPTR;
FSTPTR := LPT1; LPT1 := LPT2
UNTIL LPT1 = NIL;
LMIN := FSTPTR↑.CSLAB;
# # END
# # ELSE BEGIN LMIN := 1 ; LMAX := 0 END ;
# GENDEF(LBND,LMIN) ; GENDEF(UBND,LMAX) ; PUTLABEL(LCIX) ;
IF LMAX - LMIN < CIXMAX THEN
# BEGIN
# # IF FSTPTR <> NIL THEN
REPEAT
WITH FSTPTR↑ DO
BEGIN
WHILE CSLAB > LMIN DO
BEGIN GENUJPFJP(57(*UJP*),LADDR); LMIN:=LMIN+1 END;
GENUJPFJP(57(*UJP*),CSSTART);
FSTPTR := NEXT; LMIN := LMIN + 1
END
UNTIL FSTPTR = NIL;
PUTLABEL(LADDR) ;
"CTR" CTREMIT(CTRCASE, 0, FIRSTLN, CTRCASES, LINECOUNT);
END
ELSE ERROR(157) ;
IF SY = ENDSY THEN INSYMBOL ELSE ERROR(13)
END (*CASESTATEMENT*) ;
PROCEDURE REPEATSTATEMENT;
VAR LADDR: INTEGER;
"CTR" FIRSTLN : INTEGER; CTRNO : CTRRANGE;
BEGIN GENLABEL(LADDR); PUTLABEL(LADDR);
"CTR" FIRSTLN := LINECOUNT; CTRNO := CTRGEN;
"CTR" (*** COUNTER HERE ***)
REPEAT
REPEAT STATEMENT(FSYS + [SEMICOLON,UNTILSY])
UNTIL NOT (SY IN STATBEGSYS);
TEST := SY <> SEMICOLON;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = UNTILSY THEN
BEGIN INSYMBOL; EXPRESSION(FSYS); GENFJP(LADDR) ;
"CTR" CTREMIT(CTRREPEAT, CTRNO, FIRSTLN, 0, LINECOUNT)
END
ELSE ERROR(53)
END (*REPEATSTATEMENT*) ;
PROCEDURE WHILESTATEMENT;
VAR LADDR, LCIX: INTEGER;
"CTR" FIRSTLN : INTEGER; CTRNO : CTRRANGE;
BEGIN GENLABEL(LADDR); PUTLABEL(LADDR);
EXPRESSION(FSYS + [DOSY]); GENLABEL(LCIX); GENFJP(LCIX);
IF SY = DOSY THEN INSYMBOL ELSE ERROR(54);
"CTR" FIRSTLN := LINECOUNT; CTRNO := CTRGEN;
(*** COUNTER HERE ***)
STATEMENT(FSYS); GENUJPFJP(57(*UJP*),LADDR); PUTLABEL(LCIX) ;
"CTR" CTREMIT(CTRWHILE, CTRNO, FIRSTLN, 0, LINECOUNT);
END (*WHILESTATEMENT*) ;
(** FORSTATEMENT WITHSTATEMENT **)
PROCEDURE FORSTATEMENT;
VAR LATTR: ATTR; LSP: STP; LSY: SYMBOL;
# LCIX, LADDR: LABELRNG ; LLC : ADDRRANGE ;
"CTR" FIRSTLN : INTEGER; CTRNO : CTRRANGE;
BEGIN
IF SY = IDENT THEN
BEGIN SEARCHID([VARS],LCP);
WITH LCP↑, LATTR DO
# BEGIN TYPTR := IDTYPE; KIND := VARBL; BTYPE := TYPTR ;
IF VKIND = ACTUAL THEN
BEGIN ACCESS := DRCT; VLEVEL := VLEV;
DPLMT := VADDR ;
### IF GET_STAT THEN
### WRITE(QRR, ' #MOD', CHR( GETTYPE(BTYPE) ), ' ':2,
### ' #DIR', VLEVEL:3, DPLMT:8, ' #MND ' ) ;
END
ELSE BEGIN ERROR(155); TYPTR := NIL END
END;
IF LATTR.TYPTR <> NIL THEN
IF (LATTR.TYPTR↑.FORM > SUBRANGE)
OR COMPTYPES(REALPTR,LATTR.TYPTR) THEN
BEGIN ERROR(143); LATTR.TYPTR := NIL END;
INSYMBOL
END
ELSE
BEGIN ERROR(2); SKIP(FSYS + [BECOMES,TOSY,DOWNTOSY,DOSY]) END;
IF SY = BECOMES THEN
BEGIN INSYMBOL; EXPRESSION(FSYS + [TOSY,DOWNTOSY,DOSY]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <> SCALAR THEN ERROR(144)
ELSE
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
BEGIN LOAD;
# IF DEBUG THEN CHKBNDS(LATTR.TYPTR) ; STORE(LATTR) ;
END
ELSE ERROR(145)
END
ELSE
BEGIN ERROR(51); SKIP(FSYS + [TOSY,DOWNTOSY,DOSY]) END;
IF SY IN [TOSY,DOWNTOSY] THEN
BEGIN LSY := SY; INSYMBOL; EXPRESSION(FSYS + [DOSY]);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM <> SCALAR THEN ERROR(144)
ELSE
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
# BEGIN LOAD; IF DEBUG THEN CHKBNDS(LATTR.TYPTR) ;
(*EJG 13NOV78*) IF NOT COMPTYPES(LATTR.TYPTR,INTPTR) THEN GEN0(61(*ORD*));
# ALIGN(LC,INTSIZE) ; LLC := LC ;
# GEN3(56(*STR*),ORD('I'),LEVEL,LLC);
# GATTR := LATTR; LOAD;
(*EJG 13NOV78*) IF NOT COMPTYPES(LATTR.TYPTR,INTPTR) THEN GEN0(61(*ORD*));
# GEN3(54(*LOD*),ORD('I'),LEVEL,LLC);
# LC := LC + INTSIZE;
# IF LC > LCMAX THEN LCMAX := LC;
# IF LSY = TOSY THEN GEN2(52(*LEQ*),ORD('I'),1)
# ELSE GEN2(48(*GEQ*),ORD('I'),1);
END
ELSE ERROR(145)
END
ELSE BEGIN ERROR(55); SKIP(FSYS + [DOSY]) END;
# GENLABEL(LADDR) ; GENLABEL(LCIX); GENUJPFJP(33(*FJP*),LCIX);
# PUTLABEL(LADDR) ; (*BEGINNING OF THE FOR 'LOOP'*)
IF SY = DOSY THEN INSYMBOL ELSE ERROR(54);
"CTR" FIRSTLN := LINECOUNT; CTRNO := CTRGEN;
(*** COUNTER HERE ***)
STATEMENT(FSYS);
# GATTR := LATTR ; LOAD ;
IF NOT COMPTYPES(LATTR.TYPTR,INTPTR) THEN GEN0(61(*ORD*));(*EJG13NOV*)
# GEN3(54(*LOD*),ORD('I'),LEVEL,LLC) ;
# GEN2(55(*NEQ*),ORD('I'),1) ; GENUJPFJP(33(*FJP*),LCIX) ;
# GATTR := LATTR; LOAD;
# IF LSY = TOSY THEN GEN2(23(*INC*),GETTYPE(GATTR.BTYPE),1)
# ELSE GEN2(22(*DEC*),GETTYPE(GATTR.BTYPE),1);
# IF DEBUG THEN CHKBNDS(LATTR.TYPTR) ;
STORE(LATTR); GENUJPFJP(57(*UJP*),LADDR); PUTLABEL(LCIX);
LC := LLC ;
"CTR" CTREMIT(CTRFOR, CTRNO, FIRSTLN, 0, LINECOUNT);
END (*FORSTATEMENT*) ;
PROCEDURE WITHSTATEMENT;
# VAR LCP: CTP; LCNT: DISPRANGE; LLC: ADDRRANGE;
BEGIN LCNT := TOP ; LLC := LC ;
REPEAT
IF SY = IDENT THEN
BEGIN SEARCHID([VARS,FIELD],LCP); INSYMBOL END
ELSE BEGIN ERROR(2); LCP := UVARPTR END;
SELECTOR(FSYS + [COMMA,DOSY],LCP);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR↑.FORM = RECORDS THEN
IF TOP < DISPLIMIT THEN
# BEGIN TOP := TOP + 1;
WITH DISPLAY[TOP] DO
BEGIN FNAME := GATTR.TYPTR↑.FSTFLD;
FLABEL := NIL
END;
IF GATTR.ACCESS = DRCT THEN
WITH DISPLAY[TOP] DO
BEGIN OCCUR := CREC; CLEV := GATTR.VLEVEL;
CDSPL := GATTR.DPLMT
END
ELSE
# BEGIN LOADADDRESS; ALIGN(LC,PTRSIZE) ;
# GEN3(56(*STR*),ORD('A'),LEVEL,LC);(*=GETTYPE(GAT.TYP)*)
WITH DISPLAY[TOP] DO
BEGIN OCCUR := VREC; VDSPL := LC END;
# LC := LC + PTRSIZE;
IF LC > LCMAX THEN LCMAX := LC
END
END
ELSE ERROR(250)
ELSE ERROR(140);
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = DOSY THEN INSYMBOL ELSE ERROR(54);
STATEMENT(FSYS);
# TOP := LCNT ; LC := LLC ;
END (*WITHSTATEMENT*) ;
BEGIN (*STATEMENT*)
IF SY = INTCONST THEN (*LABEL*)
# BEGIN TTOP := TOP ;
# WHILE DISPLAY[TTOP].OCCUR <> BLCK DO TTOP := TTOP-1 ;
# LLP := DISPLAY[TTOP].FLABEL;
WHILE LLP <> NIL DO
WITH LLP↑ DO
IF LABVAL = VAL.IVAL THEN
BEGIN IF DEFINED THEN ERROR(165);
PUTLABEL(LABNAME); DEFINED := TRUE;
"CTR" CTRNO := CTRGEN;
"CTR" CTREMIT(CTRLBL, CTRNO, LINECOUNT, 0, LINECOUNT);
"CTR" (*** COUNTER HERE ***)
GOTO 1
END
ELSE LLP := NEXTLAB;
ERROR(167);
1: INSYMBOL;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5)
END;
IF NOT (SY IN FSYS + [IDENT]) THEN
BEGIN ERROR(6); SKIP(FSYS) END;
IF SY IN STATBEGSYS + [IDENT] THEN
BEGIN
CASE SY OF
IDENT: BEGIN SEARCHID([VARS,FIELD,FUNC,PROC],LCP); INSYMBOL;
IF LCP↑.KLASS = PROC THEN CALL(FSYS,LCP)
ELSE ASSIGNMENT(LCP)
END;
BEGINSY: BEGIN INSYMBOL; COMPOUNDSTATEMENT END;
GOTOSY: BEGIN INSYMBOL; GOTOSTATEMENT END;
IFSY: BEGIN INSYMBOL; IFSTATEMENT END;
CASESY: BEGIN INSYMBOL; CASESTATEMENT END;
WHILESY: BEGIN INSYMBOL; WHILESTATEMENT END;
REPEATSY: BEGIN INSYMBOL; REPEATSTATEMENT END;
FORSY: BEGIN INSYMBOL; FORSTATEMENT END;
WITHSY: BEGIN INSYMBOL; WITHSTATEMENT END
END;
IF NOT (SY IN [SEMICOLON,ENDSY,ELSESY,UNTILSY]) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END
END (*STATEMENT*) ;
BEGIN (*BODY*)
# IF FPROCP <> NIL THEN
# BEGIN ENTNAME := FPROCP↑.PFNAME ; PROCNAME := FPROCP↑.NAME ; END
# ELSE PROCNAME := '$MAINBLK ' ;
# GENCUPENT(32(*ENT*),PROCTYPE(FPROCP),SEGSIZE,ENTNAME,PROCNAME) ;
###
### NEW(CALL_HEAD) ;
### CALL_HEAD↑.NAME := BLANK12 ; CALL_HEAD↑.NXT := NIL ;
### LOCAL_CALL := FALSE ; MODIFYING := FALSE ;
### VAR_REF := 0 ; VAR_MOD := 0 ;
### WRITELN(QRR, '#BGN ', PROCNAME, LEVEL:4) ;
###
#
# IF FPROCP = NIL THEN (* ENTERING MAIN BLOCK *)
BEGIN
SAVEID := ID;
WHILE FEXTFILEP <> NIL DO
BEGIN
WITH FEXTFILEP↑ DO
BEGIN ID := FILENAME;
PRTERR := FALSE ; SEARCHID([VARS],LLCP); PRTERR := TRUE ;
IF LLCP <> NIL THEN
IF LLCP↑.IDTYPE↑.FORM <> FILES THEN
LLCP := NIL;
# IF LLCP = NIL THEN
# BEGIN
# WRITELN('**** UNDECLARED EXTERNAL FILE:':40, ID:10);
# ERROR(398) ;
# END
# ELSE (* OPEN THE FILES REQUESTED ABOVE *)
# WITH LLCP↑ DO
# BEGIN
# IF GEBCDFIL THEN GEN2(50(*LDA*),1,VADDR+1000)
# ELSE GEN2(50(*LDA*),1,VADDR) ;
# GEN1(30(*CSP*),31(*SIO*)) ;
# IF ODD(VADDR) THEN GEN1(30(*CSP*),4(*REW*))
# ELSE GEN1(30(*CSP*),3(*RES*)) ;
# GEN1(30(*CSP*),30(*EIO*)) ;
# END ;
END;
FEXTFILEP := FEXTFILEP↑.NEXTFILE
END;
ID := SAVEID;
"CTR" IF CTROPTION THEN
"CTR" BEGIN
"CTR" GENLABEL(CTRCNTLBL) ; GENUJPFJP(38(*CTS*), CTRCNTLBL) ;
"CTR" END ;
END (* PROCESSING MAIN BLOCK *)
ELSE (* FPROCP <> NIL ==> COPY MULTIPLE VALUES INTO LOCAL CELLS*)
# BEGIN LLC1 := LCAFTMST ;
# IF FPROCP↑.SAVEFP THEN LLC1 := LCAFTMST+FPSAVEAREA ;
LCP := FPROCP↑.NEXT;
WHILE LCP <> NIL DO
WITH LCP↑ DO
BEGIN
IF KLASS = VARS THEN
IF IDTYPE <> NIL THEN
# IF VKIND = FORMAL THEN (* VAR PARAMETER *)
# BEGIN ALIGN(LLC1,PTRSIZE) ;
# LLC1 := LLC1+PTRSIZE ;
# END
# ELSE (* VKIND = ACTUAL *)
# IF IDTYPE↑.FORM > POWER THEN
# BEGIN
# ALIGN(LLC1,PTRSIZE) ;
# GEN2(50(*LDA*),LEVEL,VADDR);
# GEN3(54(*LOD*),ORD('A'),LEVEL,LLC1);
# GEN1(40(*MOV*),IDTYPE↑.SIZE);
# LLC1 := LLC1 + PTRSIZE
# END
# ELSE (* FORM <= POWER *)
# BEGIN
# ALIGN(LLC1,IDTYPE↑.ALN) ; LLC1 := LLC1 + IDTYPE↑.SIZE ;
# END ;
LCP := LCP↑.NEXT;
END;
END;
"CTR" FIRSTLN := LINECOUNT; CTRNO := CTRGEN;
"CTR" (*** COUNTER HERE ***)
LCMAX := LC;
(* COMPILE THE STATEMENTS WITHIN THIS BLOCK (BODY) *)
REPEAT
REPEAT STATEMENT(FSYS + [SEMICOLON,ENDSY])
UNTIL NOT (SY IN STATBEGSYS);
TEST := SY <> SEMICOLON;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = ENDSY THEN "INSYMBOL" (*PEG*)
BEGIN
ENDFLG := TRUE;
INSYMBOL;
ENDFLG := FALSE;
END (*PEG*)
ELSE ERROR(13);
LLP := DISPLAY[TOP].FLABEL; (*TEST FOR UNDEFINED LABELS*)
WHILE LLP <> NIL DO
WITH LLP↑ DO
BEGIN
IF NOT DEFINED THEN
BEGIN
# WRITELN(OUTPUT,'**** UNDEF. LABEL:':28,LABVAL); ERROR(168) ;
END;
LLP := NEXTLAB
END;
"CTR" CTREMIT(CTRPROC, CTRNO, FIRSTLN, 0, LINECOUNT);
"CTR" IF FPROCP = NIL THEN (* RESET COUNTERS *)
"CTR" BEGIN
"CTR" CTREMIT(CTRPROC, 0, 0, 0, 0); (* EOF FOR COUNTER TABLE *)
"CTR" IF ODD(CTRCNT) THEN CTRCNT := CTRCNT+1 ;
"CTR" IF CTROPTION THEN GENDEF(CTRCNTLBL, CTRCNT) ;
"CTR" END ;
# GEN1(42(*RET*),PROCTYPE(FPROCP)); ALIGN(LCMAX,MXDATASZE) ;PRTIC := FALSE ;
# IF PRCODE THEN
BEGIN GENDEF(SEGSIZE,LCMAX) ;
IF FPROCP = NIL THEN GEN0(43(*STP*) ) ;
END ;
"IF (FPROCP = NIL) AND PRTABLES THEN PRINTTABLES(TRUE) "
###
### CALL_LVL[LOCAL_CALL] := CALL_LVL[LOCAL_CALL]+1 ;
### WRITELN(QRR) ;
### WRITE(QRR, '#PROC ':8, PROCNAME:IDLNGTH, LOCAL_CALL:4, IC:6, LCMAX:10,
### ' REF./MOD. RATIO:', VAR_MOD:4, VAR_MOD+VAR_REF:6) ;
### IF (VAR_MOD+VAR_REF) = 0 THEN WRITELN(QRR,0.0:10)
### ELSE WRITELN(QRR, VAR_MOD/(VAR_MOD+VAR_REF):10) ;
### WHILE CALL_HEAD↑.NXT <> NIL DO
### BEGIN
### WRITE(QRR, ' ', CALL_HEAD↑.NAME, CALL_HEAD↑.LVL:3, CALL_HEAD↑.CNT: 4);
### CALL_HEAD := CALL_HEAD↑.NXT ;
### END ;
### WRITELN(QRR) ; WRITELN(QRR, '#END') ;
###
# OLDIC := OLDIC+ IC ; IC := 0 ; (* RESET IC FOR NEXT PROC *)
END (*BODY*) ;
"S1"
(** MKNAME PROGRAMME STDNAMES ENTERSTDTYPES **)
"S1" PROCEDURE MKNAME(VAR ALB: ALPHA; NLB: INTEGER ) ;
"S1" VAR I, J: INTEGER ;
"S1"
"S1" BEGIN
"S1" I := 1 ;
"S1" WHILE (I < 6) AND (ALB[I] <> ' ') DO
"S1" BEGIN IF ALB[I] = '_' THEN ALB[I] := '$' ; I := I+1 END ;
"S1" FOR J := 8 DOWNTO I DO
"S1" BEGIN
"S1" ALB[J] := CHR( ORD('0')+ NLB MOD 10 ) ;
"S1" NLB := NLB DIV 10 ;
"S1" END ;
"S1" END (*MKNAME*) ;
BEGIN (*BLOCK*)
" DP := TRUE;" GENLABEL(SEGSIZE) ;
REPEAT
IF SY = LABELSY THEN
BEGIN INSYMBOL; LABELDECLARATION END;
IF SY = CONSTSY THEN
BEGIN INSYMBOL; CONSTDECLARATION END;
IF SY = TYPESY THEN
BEGIN INSYMBOL; TYPEDECLARATION END;
IF SY = VARSY THEN
BEGIN INSYMBOL; VARDECLARATION END;
"S1"
"S1" WRITE(PRR, ' SST ', CHR( PROCTYPE(FPROCP) ):1, ' ') ;
"S1" IF FPROCP = NIL THEN
"S1""LCW" WRITELN(PRR, '$MAINBLK', 1:8, 0:8, 0:8, LC-LASTFILBUF:8, 0:8)
"S1" ELSE
"S1" WITH FPROCP↑ DO
"S1" BEGIN ID := NAME ; MKNAME(ID, PFNAME) ; ALIGN(LC,MXDATASZE) ;
"S1""LCW" WRITELN(PRR, ID:8, PFLEV+1:8, FPRMSZE:8, SPRMSZE:8,
"S1""LCW" LC-LCAFTMST-FPRMSZE-SPRMSZE:8, RPRMSZE:8) ;
"S1" END ;
"S1"
WHILE SY IN [PROCSY,FUNCSY] DO
BEGIN LSY := SY; INSYMBOL; PROCDECLARATION(LSY) END;
IF SY <> BEGINSY THEN
BEGIN ERROR(18); SKIP(FSYS) END
UNTIL SY IN STATBEGSYS;
DP := FALSE;
IF SY = BEGINSY THEN INSYMBOL ELSE ERROR(17);
REPEAT BODY(FSYS + [CASESY]);
IF SY <> FSY THEN
BEGIN ERROR(6); SKIP(FSYS + [FSY]) END
UNTIL (SY = FSY) OR (SY IN BLOCKBEGSYS);
# DP := TRUE ;
END (*BLOCK*) ;
PROCEDURE PROGRAMME(FSYS:SETOFSYS);
VAR EXTFP:EXTFILEP;
BEGIN
### REWRITE(QRR) ; (* USED FOR EXTRA INFO ABOUT PROGRAM *)
"E" REWRITE(SYMTBL);
### CALL_LVL[FALSE] := 0 ; CALL_LVL[TRUE] := 0 ;
IF SY = PROGSY THEN
BEGIN INSYMBOL; IF SY <> IDENT THEN ERROR(2); INSYMBOL;
IF NOT (SY IN [LPARENT,SEMICOLON]) THEN ERROR(14);
IF SY = LPARENT THEN
BEGIN
REPEAT INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(EXTFP);
WITH EXTFP↑ DO
BEGIN FILENAME := ID; NEXTFILE := FEXTFILEP ;
GEBCDFIL := EBCDFLG ; EBCDFLG := FALSE
END;
FEXTFILEP := EXTFP;
INSYMBOL;
IF NOT ( SY IN [COMMA,RPARENT] ) THEN ERROR(20)
END
ELSE ERROR(2)
UNTIL SY <> COMMA;
IF SY <> RPARENT THEN ERROR(4);
INSYMBOL
END;
IF SY <> SEMICOLON THEN ERROR(14)
ELSE INSYMBOL;
END;
"E" WRITELN(SYMTBL,'% $MAINBLK 0');
REPEAT BLOCK(FSYS,PERIOD,NIL);
IF SY <> PERIOD THEN ERROR(21)
UNTIL SY = PERIOD ;
### WRITELN(QRR,'#HLT CALL_RATIO', CALL_LVL[TRUE]:4, CALL_LVL[FALSE]:4,
### CALL_LVL[TRUE]+CALL_LVL[FALSE]:4) ;
# IF ERRINX > 0 THEN PRINTERROR ;
END (*PROGRAMME*) ;
PROCEDURE STDNAMES;
BEGIN
NA[ 1] := 'FALSE '; NA[ 2] := 'TRUE ';
NA[ 5] := 'GET '; NA[ 6]:= 'PUT ';
NA[ 7] := 'RESET '; NA[ 8] := 'REWRITE '; NA[ 9]:= 'READ ';
NA[10] := 'WRITE '; NA[11] := 'PACK '; NA[12]:= 'UNPACK ';
NA[13] := 'NEW '; NA[14] := 'RELEASE '; NA[15]:= 'READLN ';
NA[16] := 'WRITELN '; NA[17] := 'MARK '; NA[18]:= 'TRAP ';
NA[19] := 'EXIT ';
NA[20] := 'ABS '; NA[21] := 'SQR '; NA[22]:= 'TRUNC ';
NA[23] := 'ODD '; NA[24] := 'ORD '; NA[25]:= 'CHR ';
NA[26] := 'PRED '; NA[27] := 'SUCC '; NA[28]:= 'CLOCK ';
NA[29] := 'EOF '; NA[30] := 'EOLN ';
NA[31] := 'SIN '; NA[32] := 'COS '; NA[33]:= 'EXP ';
NA[34] := 'SQRT '; NA[35] := 'LN '; NA[36]:= 'ARCTAN ';
# NA[39] := 'INPUT '; NA[40] := 'OUTPUT '; NA[41]:= 'PRD ';
# NA[42] := 'PRR '; NA[43] := 'QRD '; NA[44]:= 'QRR ';
END (*STDNAMES*) ;
PROCEDURE ENTERSTDTYPES;
VAR SP: STP;
BEGIN (*TYPE UNDERLIEING:*)
(*******************)
NEW(INTPTR,SCALAR,STANDARD); (*INTEGER*)
WITH INTPTR↑ DO
BEGIN SIZE := INTSIZE; ALN := INTSIZE ;
FORM := SCALAR; SCALKIND := STANDARD END;
NEW(REALPTR,SCALAR,STANDARD); (*REAL*)
WITH REALPTR↑ DO
" BEGIN SIZE := REALSIZE; ALN := MXDATASZE ;" (*LCW*)
BEGIN SIZE := REALSIZE; ALN := REALSIZE ; (*LCW *)
FORM := SCALAR; SCALKIND := STANDARD END;
NEW(CHARPTR,SCALAR,STANDARD); (*CHAR*)
WITH CHARPTR↑ DO
BEGIN SIZE := CHARSIZE; ALN := CHARSIZE ;
FORM := SCALAR; SCALKIND := STANDARD END;
NEW(BOOLPTR,SCALAR,DECLARED); (*BOOLEAN*)
WITH BOOLPTR↑ DO
BEGIN SIZE := BOOLSIZE; ALN := BOOLSIZE ;
FORM := SCALAR; SCALKIND := DECLARED END;
NEW(NILPTR,POINTER); (*NIL*)
WITH NILPTR↑ DO
BEGIN ELTYPE := NIL; SIZE := PTRSIZE; ALN := PTRSIZE ;
FORM := POINTER END;
NEW(TEXTPTR,FILES); (*TEXT*)
WITH TEXTPTR↑ DO
BEGIN FILTYPE := CHARPTR; SIZE := CHARSIZE; ALN := CHARSIZE ;
FORM := FILES END ;
NEW(ALFAPTR,ARRAYS); (*ALFA*)
WITH ALFAPTR↑ DO
BEGIN AELTYPE := CHARPTR; SIZE := 10*CHARSIZE ; ALN := CHARSIZE ;
FORM := ARRAYS ;
NEW(INXTYPE,SUBRANGE) ;
INXTYPE↑.RANGETYPE := INTPTR;
INXTYPE↑.MIN.IVAL := 1; INXTYPE↑.MAX.IVAL := 10;
(* OTHER FIELDS ARE IRRELEVENT !!! *)
END ;
END (*ENTERSTDTYPES*) ;
(** ENTSTDNAMES ENTERUNDECL **)
PROCEDURE ENTSTDNAMES;
VAR CP,CP1: CTP; I: INTEGER;
BEGIN (*NAME:*)
(*******)
NEW(CP,TYPES); (*INTEGER*)
WITH CP↑ DO
BEGIN NAME := 'INTEGER '; IDTYPE := INTPTR; KLASS := TYPES END;
ENTERID(CP);
NEW(CP,TYPES); (*REAL*)
WITH CP↑ DO
BEGIN NAME := 'REAL '; IDTYPE := REALPTR; KLASS := TYPES END;
ENTERID(CP);
NEW(CP,TYPES); (*CHAR*)
WITH CP↑ DO
BEGIN NAME := 'CHAR '; IDTYPE := CHARPTR; KLASS := TYPES END;
ENTERID(CP);
NEW(CP,TYPES); (*BOOLEAN*)
WITH CP↑ DO
BEGIN NAME := 'BOOLEAN '; IDTYPE := BOOLPTR; KLASS := TYPES END;
ENTERID(CP);
NEW(CP,TYPES); (*CHAR*)
WITH CP↑ DO
BEGIN NAME := 'TEXT '; IDTYPE := TEXTPTR; KLASS := TYPES END;
ENTERID(CP);
NEW(CP,TYPES); (*ALFA*)
WITH CP↑ DO
BEGIN NAME := 'ALFA '; IDTYPE := ALFAPTR ; ; KLASS := TYPES END ;
ENTERID(CP);
CP1 := NIL;
FOR I := 1 TO 2 DO
BEGIN NEW(CP,KONST); (*FALSE,TRUE*)
WITH CP↑ DO
BEGIN NAME := NA[I]; IDTYPE := BOOLPTR;
NEXT := CP1; VALUES.IVAL := I - 1; KLASS := KONST
END;
ENTERID(CP); CP1 := CP
END;
BOOLPTR↑.FCONST := CP;
NEW(CP,KONST); (*NIL*)
WITH CP↑ DO
BEGIN NAME := 'NIL '; IDTYPE := NILPTR;
NEXT := NIL; VALUES.IVAL := 0; KLASS := KONST
END;
ENTERID(CP);
# FOR I := 39 TO 44 DO
BEGIN NEW(CP,VARS); (*INPUT,OUTPUT*)
WITH CP↑ DO (*PRD,PRR*)
BEGIN NAME := NA[I]; IDTYPE := TEXTPTR; (*QRD,QRR*)
KLASS := VARS; VKIND := ACTUAL; NEXT := NIL; VLEV := 1;
# VADDR := FIRSTFILBUF+(I-39)*CHARSIZE ; EBCD := FALSE ;
END;
ENTERID(CP)
END;
# FOR I := 5 TO 36 DO (*GET...ATAN*)
## # BEGIN NEW(CP,PROC,STANDARD); (*GET,PUT,RESET*)
## # WITH CP↑ DO (*REWRITE,READ*)
## # BEGIN NAME := NA[I]; IDTYPE := NIL; (*WRITE,PACK*)
## # NEXT := NIL; KEY := I - 4; (*UNPACK,PACK*)
## # IF I <= 19 THEN KLASS := PROC ELSE KLASS := FUNC ;
## # PFDECKIND := STANDARD (*READLN,WRITELN*)
## # END; (*NEW,DISPOSE*)
## # ENTERID(CP) (*TRAP*)
## # END;
# " FOR I := 20 TO 30 DO
BEGIN NEW(CP,FUNC,STANDARD); (*ABS,SQR,TRUNC*)
WITH CP↑ DO (*ODD,ORD,CHR*)
BEGIN NAME := NA[I]; IDTYPE := NIL; (*PRED,SUCC*)
NEXT := NIL; KEY := I - 19; (*CLOCK,EOF,EOLN *)
KLASS := FUNC; PFDECKIND := STANDARD
END;
ENTERID(CP)
END;
NEW(CP,VARS); (*PARAMETER OF PREDECLARED FUNCTIONS*)
WITH CP↑ DO
BEGIN NAME := BLANK12; IDTYPE := REALPTR; KLASS := VARS;
VKIND := ACTUAL; NEXT := NIL; VLEV := 1; VADDR := 0
END;
# FOR I := 31 TO 37 DO
BEGIN NEW(CP1,FUNC,DECLARED,ACTUAL); (*SIN,COS,EXP,SQRT*)
WITH CP1↑ DO (*LN,ARCTAN,EXIT*)
BEGIN NAME := NA[I]; IDTYPE := REALPTR; NEXT := CP;
FWDECL := FALSE; EXTRN := TRUE; PFLEV := 0; PFNAME := I - 16;
KLASS := FUNC; PFDECKIND := DECLARED; PFKIND := ACTUAL
END;
ENTERID(CP1)
END;
# WITH CP1↑ DO (*FIXUPS FOR EXIT PROCEDURE*)
# BEGIN IDTYPE := NIL; NEXT := CP; KLASS := PROC END;
# NEW(CP,VARS); (*PARAMETER OF EXIT ROUTINE*)
# WITH CP↑ DO
# BEGIN NAME := BLANK12; IDTYPE := INTPTR; KLASS := VARS;
# VKIND := ACTUAL; NEXT := NIL; VLEV := 1; VADDR := 0
# END; "
END (*ENTSTDNAMES*) ;
PROCEDURE ENTERUNDECL;
VAR TMPLABEL: INTEGER; (*KLUDGE FOR XSL10*)
BEGIN
NEW(UTYPPTR,TYPES);
WITH UTYPPTR↑ DO
BEGIN NAME := BLANK12; IDTYPE := NIL; KLASS := TYPES END;
NEW(UCSTPTR,KONST);
WITH UCSTPTR↑ DO
BEGIN NAME := BLANK12; IDTYPE := NIL; NEXT := NIL;
VALUES.IVAL := 0; KLASS := KONST
END;
NEW(UVARPTR,VARS);
WITH UVARPTR↑ DO
BEGIN NAME := BLANK12; IDTYPE := NIL; VKIND := ACTUAL;
NEXT := NIL; VLEV := 0; VADDR := 0; KLASS := VARS
END;
NEW(UFLDPTR,FIELD);
WITH UFLDPTR↑ DO
BEGIN NAME := BLANK12; IDTYPE := NIL; NEXT := NIL; FLDADDR := 0;
KLASS := FIELD
END;
NEW(UPRCPTR,PROC,DECLARED,ACTUAL);
WITH UPRCPTR↑ DO
BEGIN NAME := BLANK12; IDTYPE := NIL; FWDECL := FALSE;
NEXT := NIL; EXTRN := FALSE; PFLEV := 0; GENLABEL(TMPLABEL); (*XSL10*)
PFNAME := TMPLABEL; (*XSL10*)
KLASS := PROC; PFDECKIND := DECLARED; PFKIND := ACTUAL
END;
NEW(UFCTPTR,FUNC,DECLARED,ACTUAL);
WITH UFCTPTR↑ DO
BEGIN NAME := BLANK12; IDTYPE := NIL; NEXT := NIL;
FWDECL := FALSE; EXTRN := FALSE; PFLEV := 0; GENLABEL(TMPLABEL);(*XSL10*)
PFNAME := TMPLABEL; (*XSL10*)
KLASS := FUNC; PFDECKIND := DECLARED; PFKIND := ACTUAL
END
END (*ENTERUNDECL*) ;
(** INITSCALARS INITSETS INITTABLES RESWORDS SYMBOLS RATORS PROCMNEMONICS **)
PROCEDURE INITSCALARS;
VAR I:INTEGER;
BEGIN FWPTR := NIL;
PRTABLES := FALSE; LIST := TRUE; PRCODE := TRUE;
DP := TRUE; PRTERR := TRUE; ERRINX := 0;
INTLABEL := 0; KK := IDLNGTH; FEXTFILEP := NIL;
# LC := LASTFILBUF ; (*ADR. OF THE FIRST VARIABLE OF 'MAIN BLOCK'*)
(* NOTE IN THE ABOVE RESERVATION OF BUFFER STORE FOR TEXT FILES *)
OLDIC := 0; IC := 0 ; EOL := FALSE; LINECOUNT := 1; (*PEG*)
# CH := ' '; CHCNT := 0; CHCNTMAX := DEF_CHCNTMAX; (*PEG*)
GLOBTESTP := NIL;
MXINT10 := MAXINT DIV 10; "DIGMAX := REALLNGTH - 1;"
# PROCLAB := 0; ERRORCOUNT :=0 ; ASSEMBLE:= FALSE;
SEQNUMBERS := FALSE ; FOR I := 1 TO 8 DO SEQFLD[I] := ' '; (*PEG*)
# SAVEREGS := TRUE ; SAVEFPRS := TRUE ; EBCDFLG := FALSE ;
# DEBUG := FALSE ; BYTEON := FALSE ; ASSIGN := FALSE ;
# ENDFLG := FALSE; DOTFLG := FALSE ; NXTFILBUF := FIRSTFILBUF+6 ;
# PACKDATA := FALSE ; XLINK := FALSE ; (*GENERATES UNIQUE NAMES *)
"S0" " MXDATASZE := REALSIZE ; "
"S1" MXDATASZE := PTRSIZE ; (* DON'T CHANGE THIS ALONE *)
### GET_STAT := FALSE ; ASMVERB := FALSE ;
"CTR" CTRCNT := 0 ; CTROPTION := FALSE ;
FOR I := 1 TO STD_CHCNTMAX DO LINEBUF[I] := ' '; (*PEG*)
END (*INITSCALARS*) ;
PROCEDURE INITSETS;
VAR I: SETREP_INDEX; (*SETCH*)
BEGIN
CONSTBEGSYS := [ADDOP,INTCONST,REALCONST,STRINGCONST,IDENT];
SIMPTYPEBEGSYS := [LPARENT] + CONSTBEGSYS;
TYPEBEGSYS:=[ARROW,PACKEDSY,ARRAYSY,RECORDSY,SETSY,FILESY]+SIMPTYPEBEGSYS;
TYPEDELS := [ARRAYSY,RECORDSY,SETSY,FILESY];
BLOCKBEGSYS := [LABELSY,CONSTSY,TYPESY,VARSY,PROCSY,FUNCSY,
BEGINSY];
SELECTSYS := [ARROW,PERIOD,LBRACK];
FACBEGSYS := [INTCONST,REALCONST,STRINGCONST,IDENT,LPARENT,LBRACK,NOTSY];
STATBEGSYS := [BEGINSY,GOTOSY,IFSY,WHILESY,REPEATSY,FORSY,WITHSY,
CASESY];
#
# " ATOZ := ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O'] ;
# ATOZ := ATOZ + ['P','Q','R','S','T','U','V','W','X','Y','Z'] ;
# NUMERIC := ['0','1','2','3','4','5','6','7','8','9'] ; "
# ATOZ := ['A'..'Z'] ;
# NUMERIC := ['0'..'9'] ;
# ALPHANUMERIC := ATOZ + NUMERIC + ['$','_'];
#
FOR I:=0 TO SETREP_MAX DO NULL_SET[I] := [ ]; (*SETCH*)
END (*INITSETS*) ;
PROCEDURE INITTABLES;
PROCEDURE RESWORDS;
BEGIN
RW[ 1]:= 'IF '; RW[ 2]:= 'DO '; RW[ 3]:= 'OF ';
RW[ 4]:= 'TO '; RW[ 5]:= 'IN '; RW[ 6]:= 'OR ';
RW[ 7]:= 'END '; RW[ 8]:= 'FOR '; RW[ 9]:= 'VAR ';
RW[10]:= 'DIV '; RW[11]:= 'MOD '; RW[12]:= 'SET ';
RW[13]:= 'AND '; RW[14]:= 'NOT '; RW[15]:= 'THEN ';
RW[16]:= 'ELSE '; RW[17]:= 'WITH '; RW[18]:= 'GOTO ';
RW[19]:= 'CASE '; RW[20]:= 'TYPE ';
RW[21]:= 'FILE '; RW[22]:= 'BEGIN ';
RW[23]:= 'UNTIL '; RW[24]:= 'WHILE '; RW[25]:= 'ARRAY ';
RW[26]:= 'CONST '; RW[27]:= 'LABEL ';
RW[28]:= 'REPEAT '; RW[29]:= 'RECORD '; RW[30]:= 'DOWNTO ';
RW[31]:= 'PACKED '; RW[32]:= 'FORWARD '; RW[33]:= 'PROGRAM ';
RW[34]:= 'FORTRAN '; RW[35]:= 'EXTERNAL ';
RW[36]:= 'FUNCTION '; RW[37]:= 'PROCEDURE ';
FRW[1] := 1; FRW[2] := 1; FRW[3] := 7; FRW[4] := 15; FRW[5] := 22;
FRW[6] := 28; FRW[7] := 32; FRW[8] := 35; FRW[9] := 37;
# FRW[10] := 38 ; FRW[11] := 38; FRW[12] := 38; FRW[13] := 38 ;
# "SEQFLD[9] := ' '; SEQFLD[10] := ' '; " (*CLEAR EXTRA CHARS IN SEQ. FLD*)
END (*RESWORDS*) ;
PROCEDURE SYMBOLS;
BEGIN
RSY[1] := IFSY; RSY[2] := DOSY; RSY[3] := OFSY; RSY[4] := TOSY;
RSY[5] := RELOP; RSY[6] := ADDOP; RSY[7] := ENDSY; RSY[8] := FORSY;
RSY[9] := VARSY; RSY[10] := MULOP; RSY[11] := MULOP; RSY[12] := SETSY;
RSY[13] := MULOP; RSY[14] := NOTSY; RSY[15] := THENSY;
RSY[16] := ELSESY; RSY[17] := WITHSY; RSY[18] := GOTOSY;
RSY[19] := CASESY; RSY[20] := TYPESY; RSY[21] := FILESY;
RSY[22] := BEGINSY; RSY[23] := UNTILSY; RSY[24] := WHILESY;
RSY[25] := ARRAYSY; RSY[26] := CONSTSY; RSY[27] := LABELSY;
RSY[28] := REPEATSY; RSY[29] := RECORDSY; RSY[30] := DOWNTOSY;
RSY[31] := PACKEDSY; RSY[32] := FORWARDSY; RSY[33] := PROGSY;
RSY[34]:= FRTRNSY ; RSY[35] := EXTRNSY ;
RSY[36] := FUNCSY; RSY[37] := PROCSY;
SSY['+'] := ADDOP; SSY['-'] := ADDOP; SSY['*'] := MULOP;
SSY['/'] := MULOP; SSY['('] := LPARENT; SSY[')'] := RPARENT;
SSY['$'] := OTHERSY; SSY['='] := RELOP; SSY[' '] := OTHERSY;
SSY[','] := COMMA; SSY['.'] := PERIOD; SSY[''''] := OTHERSY;
SSY['!'] := LBRACK; SSY['?'] := RBRACK; SSY[':'] := COLON;
# SSY['['] := LBRACK; SSY[']'] := RBRACK; (*XSL10*)
# SSY['%'] := LBRACK;"SSY['|'] := ADDOP ;" SSY['&'] := MULOP ; (*XSL10*)
SSY['↑'] := ARROW; SSY['<'] := RELOP; SSY['>'] := RELOP;
# "SSY['¬'] := NOTSY ;" SSY[';'] := SEMICOLON; (*XSL10*)
END (*SYMBOLS*) ;
PROCEDURE RATORS;
VAR I: INTEGER; CH: CHAR;
BEGIN
FOR I := 1 TO NRSW (*NR OF RES WORDS*) DO ROP[I] := NOOP;
ROP[5] := INOP; ROP[10] := IDIV; ROP[11] := IMOD;
ROP[6] := OROP; ROP[13] := ANDOP;
# "FOR CH := '+' TO ';' DO SOP[CH] := NOOP;" (*XSL10*)
# FOR CH := ' ' TO '←' DO SOP[CH] := NOOP; (*XSL10*)
SOP['+'] := PLUS; SOP['-'] := MINUS; SOP['*'] := MUL; SOP['/'] := RDIV;
SOP['='] := EQOP;
SOP['<'] := LTOP; SOP['>'] := GTOP;
# "SOP['|'] := OROP ;" SOP['&'] := ANDOP ; (*XSL10*)
END (*RATORS*) ;
PROCEDURE PROCMNEMONICS;
BEGIN
# SNA[ 1] :='GET'; SNA[ 2] :='PUT'; SNA[ 3] :='RES'; SNA[ 4] :='REW';
SNA[ 5] :='RDC'; SNA[ 6] :='WRI'; SNA[ 7] :='WRO'; SNA[ 8] :='WRR';
SNA[ 9] :='WRC'; SNA[10] :='WRS'; SNA[11] :='PAK'; SNA[12] :='RDB';
# SNA[13] :='WRB'; SNA[14] :='RDR'; SNA[15] :='SIN'; SNA[16] :='COS';
SNA[17] :='EXP'; SNA[18] :='SQT'; SNA[19] :='LOG'; SNA[20] :='ATN';
# SNA[21] :='CLK'; SNA[22] :='WLN'; SNA[23] :='RLN'; SNA[24] :='RDI';
# SNA[25] :='EOF'; SNA[26] :='ELN'; SNA[27] :='RDS'; SNA[28] :='TRP';
# SNA[29] :='XIT'; SNA[30] :='EIO'; SNA[31] :='SIO';
END (*PROCMNEMONICS*) ;
(** INSTRMNEMONICS **)
PROCEDURE INSTRMNEMONICS;
BEGIN
MN[0] :=' ABI'; MN[1] :=' ABR'; MN[2] :=' ADI'; MN[3] :=' ADR';
MN[4] :=' AND'; MN[5] :=' DIF'; MN[6] :=' DVI'; MN[7] :=' DVR';
MN[8] :=' SBR'; MN[9] :=' FLO'; MN[10] :=' FLT'; MN[11] :=' INN';
MN[12] :=' INT'; MN[13] :=' IOR'; MN[14] :=' MOD'; MN[15] :=' MPI';
MN[16] :=' MPR'; MN[17] :=' NGI'; MN[18] :=' NGR'; MN[19] :=' NOT';
MN[20] :=' ODD'; MN[21] :=' SBI'; MN[22] :=' DEC'; MN[23] :=' INC';
MN[24] :=' SQI'; MN[25] :=' SQR'; MN[26] :=' STO'; MN[27] :=' TRC';
MN[28] :=' UNI'; MN[29] :=' SGS'; MN[30] :=' CSP'; MN[31] :=' ';
MN[32] :=' ENT'; MN[33] :=' FJP'; MN[34] :=' '; MN[35] :=' IND';
MN[36] :=' IXA'; MN[37] :=' LCA'; MN[38] :=' CTS'; MN[39] :=' CTI';
MN[40] :=' MOV'; MN[41] :=' MST'; MN[42] :=' RET'; MN[43] :=' STP';
MN[44] :=' XJP'; MN[45] :=' CHK'; MN[46] :=' CUP'; MN[47] :=' EQU';
MN[48] :=' GEQ'; MN[49] :=' GRT'; MN[50] :=' LDA'; MN[51] :=' LDC';
MN[52] :=' LEQ'; MN[53] :=' LES'; MN[54] :=' LOD'; MN[55] :=' NEQ';
# MN[56] :=' STR'; MN[57] :=' UJP'; MN[58] :=' NEW'; MN[59] :=' SAV';
# MN[60] :=' RST'; MN[61] :=' ORD'; MN[62] :=' CHR'; MN[63] :=' DEF';
"S1" MN[64] :=' PAR';
END (*INSTRMNEMONICS*) ;
BEGIN (*INITTABLES*)
RESWORDS; SYMBOLS; RATORS;
INSTRMNEMONICS; PROCMNEMONICS;
END (*INITTABLES*) ;
BEGIN (*PASCALCOMPILER*)
(*INITIALIZE*)
(************)
INITSCALARS; INITSETS; INITTABLES;
(*ENTER STANDARD NAMES AND STANDARD TYPES:*)
(******************************************)
LEVEL := 0; TOP := 0;
WITH DISPLAY[0] DO
BEGIN FNAME := NIL; FLABEL := NIL; OCCUR := BLCK END;
ENTERSTDTYPES; STDNAMES; ENTSTDNAMES; ENTERUNDECL;
TOP := 1; LEVEL := 1;
WITH DISPLAY[1] DO
BEGIN FNAME := NIL; FLABEL := NIL; OCCUR := BLCK END;
(*COMPILE:*)
(**********)
# WRITELN(OUTPUT, ' LINE # P/D LC LVL ',
# '< STANFORD PASCAL_P COMPILER, VERSION OF AUG.-78 >' ) ;
# WRITELN(OUTPUT) ;
# CTIME := CLOCK ; (*XSL10*) (*X10S1*)
(*# CTIME := CLOCK(1); *) (*XSL10*) (*X10S1*)
#
SKIP_E_DIRECTORY; (*XSL10*)
# INSYMBOL;
# PROGRAMME(BLOCKBEGSYS+STATBEGSYS-[CASESY]);
# CTIME := (CLOCK-CTIME) DIV 10; (*XSL10*) (*X10S1*)
(*# CTIME := (CLOCK(1)-CTIME) DIV 10; *) (*XSL10*) (*X10S1*)
# WRITELN(OUTPUT); WRITELN(OUTPUT);
# IF ERRORCOUNT = 0 THEN WRITE(OUTPUT,'**** NO':19)
# ELSE WRITE(OUTPUT,'****':14,ERRORCOUNT:5) ;
# WRITELN(OUTPUT, ' SYNTAX ERROR(S) DETECTED.') ; WRITELN(OUTPUT) ;
# WRITELN(OUTPUT, '****':14, LINECOUNT:6,' LINE(S) READ, ',PROCLAB:4,
# ' PROCEDURE(S) COMPILED,'); WRITELN() ;
# WRITELN('****':14, OLDIC:6,' P_INSTRUCTIONS GENERATED,',
# CTIME DIV 100 :4, '.', CTIME:2, ' SECONDS IN COMPILATION.') ;
#"EXIT(ERRORCOUNT);" (*XSL10*)
IF ERRORCOUNT <> 0 THEN (*XSL10*)
# ERREXIT(ERRORCOUNT) ; (*XSL10*)
END. (*PASCALCOMPILER*)